MySQL: Feld auf Basis des Erstelldatums durchnummerieren


Status
Dieses Thema wurde gelöst! Zur Lösung gehen…
#1
Hallo liebe Profi-Forengemeinde,

ich brauche mal wieder eure Hilfe.
Ich möchte auf Basis des Erstelldatums eines Eintrags das Feld „Anzahl“ durchnummerieren.

Sagen wir ich habe die Tabelle "Kontakte":
ID, Erstelldatum, Anzahl, User-ID (Hab leider nicht raus wie ich hier Tabellen einfügen kann)
1549362218120.png

Die Nummerierung des Feldes „Anzahl“ soll in der Tabelle „Kontakte“ pro Nutzer durchnummeriert werden. Der älteste Eintrag eines Nutzers erhält dann also die 1, der zweit älteste die 2 und so weiter.

Wäre prima wenn ihr mir (mal wieder) helfen könntet.

Beste Grüße,
Canju
 

Yaslaw

n/a
Moderator
#2
EIn Klassiker
SQL:
select 
  k1.*,
  (
    select count(k2.*) 
    from kontakte k2 
    where k2.userid = k1.userid 
      and k2.erstelldatum <= k1.erstelldatum
  ) as anzahl
from kontakte k1
 
#3
Hey Yaslaw,

wiedermal danke für die prompte Antwort.

Ich hätte vielleicht direkt beim ersten Post erwähnen sollen, dass sich die eigtl. userid in einer separaten Tabelle (id_mapping) befindet. Ich scheitere jetzt an dem LEFT JOIN um die die userid "rüber" zu bekommen

SQL:
select
  k1.*,
  (
    select count(k2.*)
    from kontakte k2
    left join id_mapping im2 on k2.id = im.internal_id
    where im2.internal_id = im1.internal_id
      and k2.erstelldatum <= k1.erstelldatum
  ) as anzahl
from kontakte k1
left join id_mapping im1 on k1.id = im.internal_id
Zudem scheint es Probleme bei count(k2.*) zu geben. Mein Client (HeidSQL) gibt mir immer einen Syntax Fehler an dieser Stelle zurück, wenn ich den Query (ohne left join) abschicke. Ändere ich das count(k2.*) in bspw. count(k2.id) - also auf ein vorhandenes Feld - wird kein Syntax Fehler mehr ausgeworfen.

Kannst du nochmal in meine Unwissenheit eingreifen?
 
#5
Die User-ID liegt in der Tabelle id_mapping.
Die Nummerierung des Felds Anzahl soll doch pro User UND auf Basis des Erstelldatums gemacht werden. Das Feld Anzahl werde ich auch als Feld anlegen und die Nummerierung dort drin speichern.

Das Ergebnis soll sein, dass ich die Felder"Anzahl", "Startort", "Zielort" in der Tabelle Kontakte per CONCAT in das Feld "Beschreibung" via Cron UPDATEn lassen, sofern neue Einträge in der Tabelle Kontakte hinzukommen.

--> [Anzahl], '. Fahrt von ', [Startort], ' nach ', [Zielort]
----> 1. Fahrt von Berlin nach Hamburg

Alle Felder liegen dabei in der Tabelle Kontakte, bis auf die User-ID, die ich irgendwie mit "verwursten" muss, damit die Nummerierung nicht nur pro Eintrag durchgeführt wird sondern pro Eintrag UND User.
 

Yaslaw

n/a
Moderator
#6
Gibts auch Fahrten ohne User? Wenn nicht, dann mach kein LEFT JOIN sondern ein INNER JOIN

SQL:
select
    k1.*,
    im1.user_id,
    (
        select count(*)
        from kontakte k2, id_mapping im2
        where k2.id = im2.internal_id
            and im2.internal_id = im1.internal_id
            and k2.erstelldatum <= k1.erstelldatum
    ) as anzahl
from kontakte k1, id_mapping im1
where k1.id = im1.internal_id
 
#7
Hey Yaslaw,

sorry, ich bin dir noch ein Feedback schuldig. Ich konnte es doch noch ohne JOIN umsetzen.
Deine erste Lösung funktioniert also nun einwandfrei.
Danke dir.
 
#8
Hi Yaslaw,

doch noch ein Nachtrag.
Der Select Befehl funktioniert wunderbar habe diesen auch erweitert. Nur der UPDATE-Befehl wirft eine Fehlermeldung weil wir Tabellen zweimal spezifizieren:
SQL Fehler (1093) Table 'cstm1' ist specified twice, both as a target for 'UPDATE' and as a separate source for data
Statement:
Code:
UPDATE tw_cstm AS cstm1
LEFT JOIN tw_1 AS tw1 ON cstm1.id_c = tw1.id
    SET
        count_tw_c=
        (
        SELECT COUNT(*)
        FROM tw_1 AS tw2, tw_cstm AS cstm2
        WHERE 1
            AND tw2.id = cstm2.id_c
            AND cstm2.internal_user_id_c = cstm1.internal_user_id_c
            AND cstm2.internal_cs_id_c = cstm1.internal_cs_id_c
            AND tw2.date_entered <= tw1.date_entered
            AND tw2.deleted = 0
        )
    WHERE 1
    AND tw1.tw_sd IS NOT NULL
(Es ist jetzt übrigends doch die Variante mit JOIN geworden... :))

Kannst du nochmal unterstützen?

Grüße,
Canju
 

Yaslaw

n/a
Moderator
#9
ui. Update auf einen JOIN mit einer Unterabfrage ist nicht schön.
Hast du mal versucht eine Select-Abfrage zu machen, die die ID des zu updatenden Datensatzes und der neue Wert beinhaltet. Diesen dann in einer Update-Abfrage verarbeiten.
 
#10
Die ID und den Wert bekomme ich doch erst durch die Unterabfrage. Das ganze soll wieder als Cron laufen und entsprechend UPDATEn sobald ein Eintrag hinzukommt.
Hast du mal versucht eine Select-Abfrage zu machen, die die ID des zu updatenden Datensatzes und der neue Wert beinhaltet. Diesen dann in einer Update-Abfrage verarbeiten.
Das klingt irgendwie als würde ich noch andere sprachen brauchen als MySQL?
 
#12
Ich habe dir dreisterweise eine PN geschickt, da ich das in fiddle nicht wirklich mit aussagekräftigen Testdaten füllen kann. Den weiteren Verlauf können wir dann gerne für ggf. andere Interessenten hier im Thread klären.
Hoffe du verzeihst mir die eine PN.
 
#13
Dein Select bringt mit den Testdaten immer nur Anzahl=1. Ist das gewollt?
SQL:
-- Dein Select
SELECT
	(
	SELECT COUNT(*)
	FROM tw_1 AS tw2, tw_cstm AS cstm2
	WHERE 1
		AND tw2.id = cstm2.id_c
		AND cstm2.internal_user_id_c = cstm1.internal_user_id_c
		AND cstm2.internal_cs_id_c = cstm1.internal_cs_id_c
		AND tw2.date_entered <= tw1.date_entered
		AND tw2.deleted = 0
	) AS anzahl,
	tw1.*
FROM tw_1 AS tw1, tw_cstm AS cstm1
WHERE 1 
		AND tw1.id = cstm1.id_c

ORDER BY tw1.date_entered ASC
 
#15
Zum eigentlichen Problem. Ist die Frage, ob das ein einmaliger oder seltener Prozess ist, oder etwas das im Minutentakt durchgeführt wird.
Beim ersteren könntest du den bequemen Weg über eine Temporary Table gehen.
SQL:
-- drop table t_prepare;

create TEMPORARY table t_prepare 
SELECT
	(
	SELECT COUNT(*)
	FROM tw_1 AS tw2, tw_cstm AS cstm2
	WHERE 1
		AND tw2.id = cstm2.id_c
		AND cstm2.internal_user_id_c = cstm1.internal_user_id_c
		AND cstm2.internal_cs_id_c = cstm1.internal_cs_id_c
		AND tw2.date_entered <= tw1.date_entered
   	AND tw2.deleted = 0
	) AS anzahl,
	tw1.*
 FROM tw_1 AS tw1, tw_cstm AS cstm1
 WHERE 1 
		AND tw1.id = cstm1.id_c
;

UPDATE tw_cstm AS cstm1, tw_1 AS tw1, t_prepare AS vw
SET cstm1.count_tw_c= anzahl
WHERE cstm1.id_c = vw.id;
 
#16
Der Cron wird einmal die Minute (Je nach Laufzeit evtl. auch alle 2 oder 3 Minuten) laufen müssen, da das UPDATE Ergebniss so schnell wie möglich sichtbar sein muss.
 
#19
ich denke das wird wird id_c sein

tw_cstm enthält ergänzende Felder zu dem gleichen datensatz aus tw_1

sprich über den join von id aus tw_1 und id_c aus tw_cstm lassen sich die datensätze zu einem "zusammenführen"
also der datensatz stellt quassi erst den gesamte eintrag dar indem wir den JOIN durchführen.
 
#20
ich denke das wird wird id_c sein

tw_cstm enthält ergänzende Felder zu dem gleichen datensatz aus tw_1

sprich über den join von id aus tw_1 und id_c aus tw_cstm lassen sich die datensätze zu einem "zusammenführen"
also der datensatz stellt quassi erst den gesamte eintrag dar indem wir den JOIN durchführen.
Vielleicht noch kurz ergänzend:
Ich habe im Querry eine Dimension in der Unterabfrage ergänzt:
AND cstm2.internal_cs_id_c = cstm1.internal_cs_id_c

Sodass gemäß dem Erstelldatum (date_entered), pro internal_user_id_c und pro internal_cs_id_c hochgezählt werden soll. Und es sollen nur Einträge berücksichtigt werden die nicht gelöscht wurden (AND tw2.deleted = 0)
Der Query den du zuletzt hier geposted hast ist also weiterhin der, der mir die Anzahl korrekt ausgibt:

SQL:
SELECT
    cstm1.count_tw_c,
    (
    SELECT COUNT(*)
    FROM tw_1 AS tw2, tw_cstm AS cstm2
    WHERE 1
        AND tw2.id = cstm2.id_c
        AND cstm2.internal_user_id_c = cstm1.internal_user_id_c
        AND cstm2.internal_cs_id_c = cstm1.internal_cs_id_c
        AND tw2.date_entered <= tw1.date_entered
        AND tw2.deleted = 0
    ) AS anzahl,
    tw1.*,
    cstm1.*
FROM tw_1 AS tw1, tw_cstm AS cstm1
WHERE 1
        AND tw1.id = cstm1.id_c
ORDER BY tw1.date_entered ASC
Nach dem neuen Schema-Export das ich dir zukommen lassen habe sollte dir jetzt also die Anzahl wieder korrekt angezeigt werden.
 
Status
Dieses Thema wurde gelöst! Zur Lösung gehen…

Neue Beiträge