0

Funktionsfeld listet mehrere Datensätze

In der Tabelle SONGS verwalten wir alle Tracks unseres Musiklabels. Jeder Song hat eine Untertabelle MITWIRKENDE um eine beliebige Anzahl an Mitwirkenden mit der Tabelle KONTAKTE zu verlinken. Jedem Mitwirkendem können in der Tabelle MITWIRKENDE unterschiedliche Rollen (Author, Composer etc. ) über ein Mehrfachauswahlfeld zugewiesen werden. 

Zur besseren Übersicht soll nun pro Rolle je ein Funktionsfeld in der Tabelle SONGS  angelegt werden und alle (KONTAKTE.Vorname + " " + KONTAKTE.Nachname) in der Form "Vorname Nachname, ..." gesammelt auflisten.

Wie könnte eine Funktion für ein "Rollen"-Feld aussehen?

Danke für Euren Input!

28 Antworten

null
    • Reinhard
    • vor 2 Jahren
    • Gemeldet - anzeigen

    hatte folgendes versucht, aber leider ohne Erfolg:

     

    join((select Mitwirkende where Rolle = 2).(Kontakt.Vorname + " " + Kontakt.Nachname), ", ")

    • Torsten_Stang.1
    • vor 2 Jahren
    • Gemeldet - anzeigen
    join(for i in Mitwirkende [Rolle=2] do i.Kontakt.Vorname + " " + i.Kontakt.Nachname), ",
    ")
    
    • Reinhard
    • vor 2 Jahren
    • Gemeldet - anzeigen

    Danke Torsten, leider klappt es nicht ganz. 

    "Symbol erwartet: end in Zeile 1, Spalte 84"

    Die fehlende Klammer habe ich bereits ergänzt, bringt aber leider nix. Danke nochmal :)

    • Torsten_Stang.1
    • vor 2 Jahren
    • Gemeldet - anzeigen

    Öhm, stimmt ;)

     

    join(for i in Mitwirkende [Rolle=2] do i.Kontakt.Vorname + " " + i.Kontakt.Nachname) end, ",
    ")
    
    
    • Reinhard
    • vor 2 Jahren
    • Gemeldet - anzeigen

    Funktion wird jetzt angenommen, gewandelt in diese Form:

     

    join(for i in Mitwirkende[Rolle = 2] do
        i.Kontakt.Vorname + " " + i.Kontakt.Nachname
    end, ", ")
    

     

    Geht aber leider immer noch nicht, bzw. wird nix angezeigt. 

    Ich erkläre es nochmal anders: In der Tabelle SONGS gibt es die Untertabelle MITWIRKENDE. In SONGS soll nun in jeweiligen Funktionsfeldern eine Namensauflistung der MITWIRKENDEN entsprechend der ROLLE-ID erfolgen.

    Bsp.:

    Person A hat Rolle 2 und 1

    Person B nur Rolle 1

     

    Funktionsfeld "Rolle 1" listet "Person A, Person B"

    Funktionsfeld "Rolle 2" listet "Person A" 

      • Torsten_Stang.1
      • vor 2 Jahren
      • Gemeldet - anzeigen

      Reinhard 

      'Mitwirkende' ist eine n:m-Beziehung von 'Song' zu 'Kontakt', oder?

      und 'Rolle' ist ein einfaches Auswahlfeld in 'Mitwirkende'?

    • Reinhard
    • vor 2 Jahren
    • Gemeldet - anzeigen

    genau so ist es Torsten :)

    • Torsten_Stang.1
    • vor 2 Jahren
    • Gemeldet - anzeigen

    mit der Funktion

    join(for i in Mitwirkende[Rolle = 2] do
        i.Kontakt.Vorname + " " + i.Kontakt.Nachname
    end, ",
    ")
    

    funktioniert's in meiner schnell erstellten DB:

    https://www.dropbox.com/s/agn5rfgj1u8sf7d/Songs.ninox?dl=0

    Schau's Dir da mal an, evtl. siehst Du so, welche Anpassungen Du für Dein Datenmodell vornehmen musst.

    • Reinhard
    • vor 2 Jahren
    • Gemeldet - anzeigen

    Hi Torsten,

    danke für Deine Mühe. Kann es sein, dass das Auswahlfeld das Problem macht? Ich habe hier stattdessen ein Mehrfachauswahlfeld (siehe vorherige Posts: Person A = Rolle 1 und Rolle 2....) benutzt, da eine Person mehrere Rollen haben kann.

    Danke nochmal!

      • Torsten_Stang.1
      • vor 2 Jahren
      • Gemeldet - anzeigen

      Reinhard genau deshalb hatte ich gefragt, ob es sich um ein "einfaches Auswahlfeld" handelt. 😉

      Mehrfachauswahlfelder werden anders abgefragt:

      join(for i in Mitwirkende[contains(concat(chosen(Rolle)), "Zwei")] do
          i.Kontakt.Vorname + " " + i.Kontakt.Nachname
      end, ",
      ")
      

      die DB hab ich entsprechend angepasst:

      https://www.dropbox.com/s/agn5rfgj1u8sf7d/Songs.ninox?dl=0

    • Reinhard
    • vor 2 Jahren
    • Gemeldet - anzeigen

    tja, was soll ich sagen.... wer lesen kann ist klar im Vorteil. 

    Sorry, mein Fehler :) Läuft jetzt wie geplant. Habe auch den 2ten Vornamen noch optional dabei:

    join(for i in Mitwirkende[contains(concat(chosen(Rolle)), "Composer")] do
        i.Kontakt.Vorname + if i.Kontakt.'Zweiter Vorname' != null then
            " " + i.Kontakt.'Zweiter Vorname'
        end + " " + i.Kontakt.Nachname
    end, ",
    ")

    Danke!

      • Torsten_Stang.1
      • vor 2 Jahren
      • Gemeldet - anzeigen

      Reinhard gerne. Das != null bei der if-Abfrage zum zweiten Vornamen kannst Du Dir sparen, 

      if i.Kontakt.'Zweiter Vorname' then

      genügt.

    • Reinhard
    • vor 2 Jahren
    • Gemeldet - anzeigen

    Super habe ich auch eingebaut.

     

    Noch etwas zum Thema: In einem Auswahlfeld (! ja diesmal wirklich) "Sprache" in der Tabelle "Songs" habe ich die Möglichkeit "ohne (Instrumental)" (ID 10) auszuwählen. Da diese Einstellung den "Author" als "Rolle" ausschließt, wäre es schön einen "alert" im Mehrfachauswahlfeld "Rolle" in der Untertabelle "Mitwirkende" auszugeben, sowie die Funktion der Auswahl dieser speziellen Rolle zu unterbinden wobei alle anderen noch funktionieren. Kriegen wir das auch noch hin?

    Nach Änderung folgendes Skript ausführen:
     

    if Songs.Sprache = 10 then
        false + alert("'Author' kann nur gewählt werden, wenn der Song eine 'Sprache' zugewiesen hat.")
    end
    

     
    Danke!
     

      • Torsten_Stang.1
      • vor 2 Jahren
      • Gemeldet - anzeigen

      Reinhard 

      Die Optionen eines Mehrfachauswahlfeldes kann man nicht dynamisch anbieten, nein.

      Hierfür würde es eines dynamischen Mehrfachauswahlfeldes bedürfen. Diese sind aber deutlich komplexer zu händeln, ob sich der Aufwand lohnt, wage ich zu bezweifeln. Zumindest muss ich da mangels Erfahrung mit dem Feldtyp passen.

      Was man in jedem Fall mit Deinem Datenmodell hinbekommt: Sobald das Feld 'Sprache' in 'Songs' die ID 10 hat, wird eine Auswahl von "Author" direkt wieder rückgängig gemacht. Allerdings benötigen wir hierzu die Options-IDs von 'Rolle' (ich hab mal 3 genommen).

      Dein Änderungstrigger des Feldes 'Rolle' könnte also so aussehen:

      if Songs.Sprache = 10 then
         let myChoice := numbers(Rolle);
         Rolle := for i in myChoice do
                 if i != 3 then i end
             end;
         alert("'Author' kann nur gewählt werden, wenn der Song eine 'Sprache' zugewiesen hat.")
      end
      
    • Reinhard
    • vor 2 Jahren
    • Gemeldet - anzeigen

    Hi Torsten,

    genial, genau das wonach ich gesucht habe. Perfekt! Habe nun auch den "alert" noch an die Bedingung geknüpft. Läuft, besten Dank!

    if Songs.Sprache = 10 then
        let myChoice := numbers('Copyright Role');
        'Copyright Role' := for i in myChoice do
                if i != 1 then
                    i
                else
                    alert("'Author' kann nur gewählt werden, wenn dem Song eine 'Sprache' zugewiesen ist.")
                end
            end
    end
    
    • Torsten_Stang.1
    • vor 2 Jahren
    • Gemeldet - anzeigen
    Reinhard said:
    Habe nun auch den "alert" noch an die Bedingung geknüpft.

     ... macht natürlich Sinn, hatte es total falsch plaziert...

    • Reinhard
    • vor 2 Jahren
    • Gemeldet - anzeigen

    Hi Torsten, da du das Datenmodell bereits kennst, frage ich hier nochmal direkt nach:

    Unser Verlagspartner möchte nun, dass wir im .csv Export der "Songs" gewisse Daten der "Mitwirkende" in weitere Spalten nebeneinander darstellen. 

    Ich hab hierzu einen Thread:
    https://forum.ninox.de/t/x2hwp61?r=m1hwpp5#m1hwpp5

    Scheinbar versteht es niemand so recht, ich denke Du weißt wie ich es meine:

    Mit first() klappt das super für die erste Zeile aus "Mitwirkende", bei den weiteren komme ich aber nicht hin. Hier hatte ich item(xxx,n) genommen, was auch klappt, so lange bis mal ein Feld leer ist, dann verrutscht alles...

    Gibt es hier eine Lösung? 

      • Torsten_Stang.1
      • vor 2 Jahren
      • Gemeldet - anzeigen

      Reinhard ich hab' den Thread gesehen - ganz ehrlich: hätte ich, wie von Dir vermutet, tatsächlich verstanden, um was es Dir geht, hätte ich mich wohl zu Wort gemeldet ;-)

    • Reinhard
    • vor 2 Jahren
    • Gemeldet - anzeigen

    Hey Torsten,

    ich hab Deine "Song" Tabelle ergänzt und die Ansicht mal so gebaut wie ich es bräuchte. Bitte teste mal bei "Thomas Genauso" aus den Nachnamen wegzulassen (wird in echt nie passieren, aber andere Felder meiner Tabelle könnten durchaus mal leer sein...). Er würde dann in der Ansicht "Thomas Bohlen" heißen da alle Felder verrutschen, sobald ein Leerfeld auftaucht.

    Kann ich das unterbinden?

    Mir ist klar, dass ich in der Ansicht immer nur eine fixe Anzahl an Mitwirkenden anzeigen kann, die Tabelle theoretisch aber unendlich sind. Mit dem kann ich aber leben.

    Danke schonmal.

      • Torsten_Stang.1
      • vor 2 Jahren
      • Gemeldet - anzeigen

      Reinhard Ahhh, jetzt weiss ich, worauf Du hinauswillst... ;-)

      mit 

      item(Mitwirkende.Kontakt.Vorname, 0)
      

      holst Du Dir das erste Element ALLER Vornamen - Du möchtest aber den Vornamen des ersten Kontakts - also besser:

      item(Mitwirkende.Kontakt, 0).Vorname
      

      Hier in der DB:

      https://www.dropbox.com/s/zq3g3b8t94q2nwx/Songs%20Hicktown%202.ninox?dl=0

    • Reinhard
    • vor 2 Jahren
    • Gemeldet - anzeigen

    Ach wie cool, mal wieder mehr als einfach. Ninox rockt, danke Torsten.

    Eine Sache hätte ich hier noch, dann kann ich alles zackig befüllen:
    Da die "Mitwirkenden" bei Alben meistens mit all ihren Daten gleich bleiben, wäre es schön über folgenden Trigger gewisse Song Daten zu kopieren und auch die Tabelle "Mitwirkende" automatisch zu erstellen. 

    Jeder Song wird über seinen ISRC sozusagen als Barcode exakt identifiziert. Und bisher nutzte ich folgenden Trigger um die Daten der Songs zu kopieren. Untertabellen habe ich allerdings noch nie automatisch generiert... 

     

    if 'Suche ISRC' then
        let myID := 'Suche ISRC';
        if cnt(select Songs where ISRC = myID) = 0 then
            alert("Die angegebene ID existiert nicht!")
        else
            let searchRecord := first(select Songs where ISRC = myID);
            Version := searchRecord.Version;
            Sprache := searchRecord.Sprache;
            Genre := searchRecord.Genre;
            'Subgenre (Rock)' := searchRecord.'Subgenre (Rock)';
            'Subgenre (Alternative)' := searchRecord.'Subgenre (Alternative)';
            'Suche ISRC' := null
        end
    else
        alert("Zuerst einen Wert in das Feld Suche ISRC eingeben")
    end
    
    • Torsten_Stang.1
    • vor 2 Jahren
    • Gemeldet - anzeigen

    Zum Verständnis:

    Du legst zu einem Album einen neuen Song an und hast dort ein Feld 'Suche ISRC', in welches Du den ISRC eines anderen Songs (wie auch immer) eingeben kannst, der zumindest ähnliche Daten hat?

     

    .. aus der Hüfte, mit der bekannten Gefahr des Datenmodell-Stolpersteins:

    let my := this;
    if 'Suche ISRC' then
        let myID := 'Suche ISRC';
        if cnt(select Songs where ISRC = myID) = 0 then
            alert("Die angegebene ID existiert nicht!")
        else
            let searchRecord := first(select Songs where ISRC = myID);
            Version := searchRecord.Version;
            Sprache := searchRecord.Sprache;
            Genre := searchRecord.Genre;
            'Subgenre (Rock)' := searchRecord.'Subgenre (Rock)';
            'Subgenre (Alternative)' := searchRecord.'Subgenre (Alternative)';
            for i in searchRecord.Mitwirkende do
                let myNew := create Mitwirkende;
                myNew.(Rolle := i.Rolle;
                    Songs := my;
                    Kontakt := i.Kontakt)
            end;
            'Suche ISRC' := null
        end
    else
        alert("Zuerst einen Wert in das Feld Suche ISRC eingeben")
    end
    

    Alternativ wie bewährt: Bau die Dummy-DB um die relevanten Felder aus und poste sie hier, dann schau ich mal rein.

     

    BTW: Die Verknüpfungen in 'Mitwirkende' zu den Tabellen 'Songs' und 'Kontakt' solltest Du mit Komposition ausführen - das hat zur Folge, dass der Datensatz dem Dasein der Mutter-Datensätze folgt (sprich: gibt's den Song nicht mehr, brauchst Du auch die n:m-Beziehung zum Kontakt nicht mehr - und umgekehrt).

    • Reinhard
    • vor 2 Jahren
    • Gemeldet - anzeigen

    Das sieht ziemlich cool aus, ich teste es gleich aus. Auf die i Variable wäre ich mal wieder nicht gekommen... die vergess ich ständig... Ich geb bescheid ob es hinhaut.

     

    Danke für den Tipp mit der Komposition. 

    • Reinhard
    • vor 2 Jahren
    • Gemeldet - anzeigen

    Klappt wie gewünscht, das flutscht jetzt. Riesen Dank nochmal :)

    • Reinhard
    • vor 2 Jahren
    • Gemeldet - anzeigen

    Hey Torsten, ich brauch nochmal Deine Hilfe wie es aussieht, du kennst nun das Datenmodell schon relativ gut:

    • Es gibt eine weitere Tabelle "Produkte" für die Erstellung von "Produkten" die mehrere "Songs" beinhalten = Alben, EPs, Singles etc. 

    • Da jeder "Song" unterschiedlichen "Produkte"  mehrmals zugewiesen werden können soll, nutze ich die Zwischentabelle "Tracks" in "Produkte"  und verknüpfe dort zu "Songs". 

    • Nun versuche ich über einen Trigger "Credits erstellen" Textfelder in "Produkte" mit den jeweiligen "Mitwirkenden" des gesamten "Produktes" anhand deren "Copyright Role" (ehemals Rolls)) zu erstellen:

    - Author

    - Composer

    - Producer etc.

    Wenn der selbe Kontakt in der jeweiligen "Copyright Role" bei mehreren / allen Titeln beteiligt war, soll dieser nur einmal im Feld unter "Produkte" gelistet werden.

    let my := this;
    join(for i in unique(Songs[Hauptprodukt = my].Mitwirkende[contains(concat(chosen('Copyright Role')), "Producer")]) do
        i.Songs.Mitwirkende.Kontakt.Vorname
    end, ", ")
    

    Irgendwie so, wollte ich es in einem Funktionsfeld testen, klappt aber nicht... Hast Du eine Idee?