Как группировать по столбцу, разделять запятой и присоединяться к другой таблице [duplicate]

Классический пример выражения для выбора без соединения, которое возвращает декартово произведение всех результатов комбинирования перечисленных таблиц.

SQL Database Solution

Просто импортируйте Animals, Fruit, Country в виде отдельных таблиц в любую базу данных SQL, такую ​​как MS Access, SQLite, MySQL и т. д. и таблицы таблиц без объединений, включая неявные (WHERE) и явные (JOIN) объединяются:

SELECT Animals.Animal, Fruits.Fruit, Countries.Country
FROM Animals, Countries, Fruits;

Excel Solution

То же понятие с запуском non-join SQL statement в VBA с использованием ODBC-соединения с книгой, содержащей диапазоны «Животные, страны и фрукты». Например, каждая группа данных находится в своем собственном листе с таким же именем.

Sub CrossJoinQuery()

    Dim conn As Object
    Dim rst As Object
    Dim sConn As String, strSQL As String

    Set conn = CreateObject("ADODB.Connection")
    Set rst = CreateObject("ADODB.Recordset")

    sConn = "Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};" _
               & "DBQ=C:\Path To\Excel\Workbook.xlsx;"
    conn.Open sConn

    strSQL = "SELECT * FROM [Animals$A1:A3], [Fruits$A1:A3], [Countries$A1:A3] "
    rst.Open strSQL, conn

    Range("A1").CopyFromRecordset rst

    rst.Close
    conn.Close

    Set rst = Nothing
    Set conn = Nothing

End Sub

1
задан jason 1 September 2014 в 20:33
поделиться

1 ответ

Вы действительно должны посмотреть на Нормализация базы данных и сначала нормализовать свою структуру, добавив таблицу переходов и удерживая отношение из таблицы, каждое отношение, хранящееся в таблице c, будет храниться в новой таблице соединений, но не разделено запятыми список каждой строки будет содержать идентификатор c и один идентификатор пользователя для каждой строки, если вы не можете изменить свою схему, вы можете использовать find_in_set для поиска значений в наборе

select *  
from  tblC c
JOIN tblB b
ON (find_in_set(b.userid,c.userids) > 0)
where c.nname="new1"

См. демонстрацию


Редактировать для нормализации схемы

Я удалил столбец userids из вашего tblC, и вместо этого я создал новую таблицу соединений как tblC_user с 2 столбца c_id это будет связано с столбцом id tblC и вторым userid, чтобы хранить пользовательские отношения пользователей для tblC, см. Примерную схему для tblC

CREATE TABLE if not exists tblC
(
id int(11) NOT NULL auto_increment ,
nname varchar(255),
 PRIMARY KEY (id)
);

INSERT INTO tblC (id, nname) VALUES
('1', 'new1'),
('2', 'new2'),
('3', 'new3'),
('4', 'new4'),
('5', 'new5');

И здесь ваша таблица соединений как tblC_user

CREATE TABLE if not exists tblC_user
(
 c_id int,
 userid int
);

INSERT INTO tblC_user (c_id,userid) VALUES
('1','1'),
('1','2'),
('2','1'),
('2','3'),
('3','1'),
('3','4'),
('4','3'),
('4','2'),
('5','5'),
('5','2');

В приведенном выше примере, если вы заметили, что я не сохранял никаких разделенных запятыми отношений, каждое отношение пользователя для tblC сохраняется в новой строке, set Я использовал таблицу соединений в join, и новый запрос будет похож на belo w

select *  
from  tblC c
join tblC_user cu on(c.id = cu.c_id)
join tblB b on (b.userid = cu.userid)
where c.nname="new1"

Демо 2

Теперь над запросом можно оптимизировать, используя индексы, вы можете легко поддерживать каскадные отношения

2
ответ дан M Khalid Junaid 31 August 2018 в 23:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: