Position einer Zeile nach Sortierung ermitteln

Montag, 29. März 2010, 00:28 Uhr von Christian

In einer Tabelle sind Artikel mit Datum versehen, wie z. B.:

item     created
----------------
  1   2010-03-10
  2   2010-03-20
  3   2010-03-21
  4   2010-03-22
  5   2010-03-23
  6   2010-03-25
  7   2010-03-26
  8   2010-03-27
  9   2010-03-28
 10   2010-03-28

Nun soll zu einem bestimmten Artikel ermittelt werden, wie neu er ist, d. h. der wievielte er wäre, wenn alle Artikel nach Datum sortiert werden würden. Beispielsweise soll für den Artikel 8 die Position 3 ausgegeben werden, da er der drittneueste Artikel ist. Das lässt sich mit folgender Abfrage lösen:

SELECT `SortedItems`.`position`
FROM (
  SELECT t.`item`,
         @rowCount := @rowCount + 1 `position`
  FROM   `Test` t,
         (SELECT @rowCount := 0) `dummyTableName_notNeeded`
  ORDER BY `created` DESC
) `SortedItems`
WHERE `SortedItems`.`item` = "8"

In der inneren Abfrage werden nun also alle Artikel absteigend nach Datum sortiert, sodass der neueste Artikel an erster Stelle steht. Dabei wird eine Variable (rowCount) verwendet, die für jeden Artikel die aktuelle Zeilennummer mitzählt und in dem Zwischenergebnis in die Spalte position einträgt. Die Variable rowCount muss zuvor mit 0 initialisiert werden. Die äußere Abfrage liefert dann lediglich die Position des gewünschten Artikels.

Auf diese Lösung hat mich ein alter Kommentar zu dem Thema in einem anderen Blog gebracht.

Für alle, die damit selbst ein wenig spielen möchten, hier die Anweisungen zum Erzeugen und Füllen der Test-Tabelle:

CREATE TABLE `Test` (
  `item` int(11) NOT NULL,
  `created` date NOT NULL,
  PRIMARY KEY (`item`)
);

INSERT `Test` (`item`, `created`) VALUES
(1, '2010-03-10'),
(2, '2010-03-20'),
(3, '2010-03-21'),
(4, '2010-03-22'),
(5, '2010-03-23'),
(6, '2010-03-25'),
(7, '2010-03-26'),
(8, '2010-03-27'),
(9, '2010-03-28'),
(10, '2010-03-28');

Geschrieben in: MySQL | Schlagwörter: ,
Keine Kommentare »

Zellen als Spalten nutzen und Werte zuordnen

Sonntag, 28. März 2010, 19:24 Uhr von Christian

In einer Tabelle sind für zwei fest definierte Kategorien A und B die jeweilige Anzahl zu den Ereignissen x und y wie folgt gegeben:

x  y  category  count
---------------------
1  2      A        10
1  2      B        20
1  3      A       100
1  3      B       200
1  4      A      1000
1  5      B      2000

Nun muss die Struktur zur Auswertung dahingehend geändert werden, dass die Kategorien A und B als Spalten und die jeweilige Anzahl als Wert in den Zeilen, gruppiert nach x und y, bereitstehen. Dazu müssen die Zeilen als Spalten ausgegeben und die jeweils zur Kategorie passende Anzahl, unter Berücksichtigung der Ereignisse, als Wert in diese Spalte geschrieben werden. Auch müssen bisher nicht definierte Anzahlen auf 0 gesetzt werden, sodass das Resultat folgendermaßen aussieht:

x  y    A     B
----------------
1  2    10    20
1  3   100   200
1  4  1000     0
1  5     0  2000

Erreicht werden kann das mit dieser Abfrage:

SELECT
  `x`, `y`,
  SUM(IF(`category` = "A", `count`, 0)) `A`,
  SUM(IF(`category` = "B", `count`, 0)) `B`
FROM `Test`
GROUP BY `x`, `y`

Hierbei wird das Ergebnis nach den Ereignissen x und y gruppiert und dabei für beide Kategorien die entsprechende Summe der Anzahl gebildet.

Das Problem dabei ist jedoch die Beschränkung auf eine vorgegebene Menge von Kategorien. Eine Lösung für variable Werte wäre interessant, lässt sich allerdings (wahrscheinlich) aufgrund der unklaren Anzahl resultierender Spalten nicht allein in SQL realisieren.

Für alle, die damit selbst ein wenig spielen möchten, hier die Anweisungen zum Erzeugen und Füllen der Test-Tabelle:

CREATE TABLE `Test` (
  `x` int(11) NOT NULL,
  `y` int(11) NOT NULL,
  `category` enum('A','B') NOT NULL,
  `count` int(11) NOT NULL
);

INSERT `Test` (`x`, `y`, `category`, `count`) VALUES
(1, 2, 'A', 10),
(1, 2, 'B', 20),
(1, 3, 'A', 100),
(1, 3, 'B', 200),
(1, 4, 'A', 1000),
(1, 5, 'B', 2000);

Geschrieben in: MySQL | Schlagwörter: ,
Keine Kommentare »