Próbuję sformatować zapytanie SQL za pomocą wielu lewej dołączenia do czytelnego pliku CSV. Kiedy robię lewą dołączyć, zwraca wiele wierszy na ten sam identyfikator (jak powinien, ponieważ istnieje wiele niepowtarzalnych wierszy dołączonych do niego), jednak nie jest to dopuszczalne dla czytelnego pliku CSV.

Chcę, aby każdy zduplikować wiersz do łączenia się z jednym rzędem z wieloma kolumnami dla duplikatów danych.

Aktualne wyniki Przyłącz Wyniki:

SELECT *
FROM people
LEFT JOIN attributes on ID

ID | Name | Attributes
1  | Ken  | Tall
1  | Ken  | Slender
1  | Ken  | Blonde
2  | John | Short

Pożądane wyniki (eksportowane do CSV):

ID | Name | Attribute 1 | Attribute 2 | Attribute 3
1    Ken    Tall          Slender       Blonde
2    John   Short

Próbowałem również podjąć grupę przez ID, ale kiedy to zrobię, właśnie zwraca jeden z atrybutów dla każdego identyfikatora, co jest również niedopuszczalne.

Może nie patrzę w odpowiednie miejsca, ale nie mogę znaleźć żadnych funkcji, aby pomóc mi osiągnąć to.

Z góry dziękuję!!!

0
SynthAura 7 czerwiec 2021, 22:16

4 odpowiedzi

Najlepsza odpowiedź

Możesz także użyć grupy_concat, nie musisz znać maksymalnej liczby atrybutów i OK dla importu CSV.

Wybierz ID, Nazwa, Group_Concat (Separatator atrybutów "; ') jako atrybuty grupy osób według ID, nazwa;

0
Dri372 7 czerwiec 2021, 19:51

Potrzebujesz warunkowej agregacji, takich jak

SELECT ID, Name, 
       MAX( CASE WHEN rn = 1 THEN attributes END ) AS attribute1, 
       MAX( CASE WHEN rn = 2 THEN attributes END ) AS attribute2,
       MAX( CASE WHEN rn = 3 THEN attributes END ) AS attribute3 
  FROM
    (
     SELECT p.ID, Name, attributes,
            ROW_NUMBER() OVER (PARTITION BY ID ORDER BY ID) AS rn
       FROM people AS p
       LEFT JOIN attributes AS a
         ON a.ID = p.attribute_ID
     ) AS pa
 GROUP BY ID, Name

Gdzie attribute_ID jest przypuszczalną kolumną z tabeli {X1}}, a funkcja okna jest używana, pod warunkiem, że wersja dB jest 8.0

Inną opcją będzie używać dynamicznego obrotu, w którym nie ma potrzeby wiedzieć, ile różnych atrybutów dla każdego człowieka i nie ma potrzeby pisać każdego warunkowego dla każdej agregacji dla atrybutów, takich jak

SET @sql = NULL;

SELECT GROUP_CONCAT(
           DISTINCT
              CONCAT(
                    'MAX(CASE WHEN rn =', rn,' THEN attributes END) AS attribute',rn
                    )
       )
  INTO @sql
  FROM 
  (
   SELECT DISTINCT ROW_NUMBER() OVER (PARTITION BY id) AS rn 
     FROM people 
    ORDER BY rn                 
  ) AS r;

SET @sql = CONCAT('SELECT ID, Name, ',@sql,
                   ' FROM
                      (
                       SELECT p.ID, Name, attributes,
                              ROW_NUMBER() OVER (PARTITION BY ID ORDER BY ID) AS rn
                         FROM people AS p
                         LEFT JOIN attributes AS a
                           ON a.ID = p.attribute_ID
                       ) AS pa
                    GROUP BY ID, Name'); 

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

Demo

1
Barbaros Özhan 7 czerwiec 2021, 20:47

Możesz także łatwo użyć grupy_concat z substring_index jak:

SELECT p.*, t.name
    , SUBSTRING_INDEX(t.attribs, ',', 1) as attribute1
    , SUBSTRING_INDEX( SUBSTRING_INDEX(t.attribs, ',', 2), ',' , -1) as attribute2
    , SUBSTRING_INDEX( SUBSTRING_INDEX(t.attribs, ',', 3), ',' , -1) as attribute3
    , SUBSTRING_INDEX( SUBSTRING_INDEX(t.attribs, ',', 4), ',' , -1) as attribute4
FROM people p
LEFT JOIN ( 
SELECT uid, name , CONCAT(GROUP_CONCAT(attribute),',,,,') as attribs FROM attributes GROUP BY name
) as t ON t.uid = p.uid;

próbka

MariaDB [bernd]> select * from people;
+----+------+
| id | uid  |
+----+------+
|  1 |    1 |
|  2 |    2 |
+----+------+
2 rows in set (0.00 sec)

MariaDB [bernd]> select * from attributes;
+----+------+------+-----------+
| id | uid  | name | attribute |
+----+------+------+-----------+
|  1 |    1 | Ken  | Tall      |
|  2 |    1 | Ken  | Slender   |
|  3 |    1 | Ken  | Blonde    |
|  4 |    2 | John | Short     |
+----+------+------+-----------+
4 rows in set (0.00 sec)

MariaDB [bernd]> SELECT p.*, t.name
    -> , SUBSTRING_INDEX(t.attribs, ',', 1) as attribute1
    -> , SUBSTRING_INDEX( SUBSTRING_INDEX(t.attribs, ',', 2), ',' , -1) as attribute2
    -> , SUBSTRING_INDEX( SUBSTRING_INDEX(t.attribs, ',', 3), ',' , -1) as attribute3
    -> , SUBSTRING_INDEX( SUBSTRING_INDEX(t.attribs, ',', 4), ',' , -1) as attribute4
    -> FROM people p
    -> LEFT JOIN ( 
    -> SELECT uid, name , CONCAT(GROUP_CONCAT(attribute),',,,,') as attribs FROM attributes GROUP BY name
    -> ) as t ON t.uid = p.uid;
+----+------+------+------------+------------+------------+------------+
| id | uid  | name | attribute1 | attribute2 | attribute3 | attribute4 |
+----+------+------+------------+------------+------------+------------+
|  1 |    1 | Ken  | Tall       | Slender    | Blonde     |            |
|  2 |    2 | John | Short      |            |            |            |
+----+------+------+------------+------------+------------+------------+
2 rows in set (0.01 sec)

MariaDB [bernd]> 
0
Bernd Buffen 7 czerwiec 2021, 20:23

Może to może być pomocne

SELECT *
FROM (SELECT ID, Name, Attributes,'Attribute ' || ROW_NUMBER () OVER (PARTITION BY Name ORDER BY ID) as columns 
   FROM   people) ppl
PIVOT Attributes FOR columns IN('Attribute 1','Attribute 2','Attribute 3'))
ORDER BY ID
0
joserobertog 7 czerwiec 2021, 20:44