我想創建基於連接表生成值的動態虛擬列。從mysql的表中創建動態創建的列
我有以下的表稱爲類型:
id, name
1, TypeA
2, TypeB
,我已經叫類
id, name, type
1, a, 1
2, b, 2
表
我想有一個返回以下
category name, TypeA, TypeB
a, 1, 0
b, 0, 1
查詢
是否可以在mysql中做到這一點?
我想創建基於連接表生成值的動態虛擬列。從mysql的表中創建動態創建的列
我有以下的表稱爲類型:
id, name
1, TypeA
2, TypeB
,我已經叫類
id, name, type
1, a, 1
2, b, 2
表
我想有一個返回以下
category name, TypeA, TypeB
a, 1, 0
b, 0, 1
查詢
是否可以在mysql中做到這一點?
有一個名爲PIVOT
的功能,它可以做你想做的,但不幸的是,它在MySQL中不可用。
你可以但是做什麼,是串連所有類型爲每個類別一個字符串:
SELECT
a.name,
GROUP_CONCAT(b.name) AS types
FROM
category a
LEFT JOIN
types b ON a.type = b.id
GROUP BY
a.id
這將導致類似:
name | types
--------------------------------
a | TypeA
b | TypeB
c | TypeA,TypeB,TypeC,TypeD
凡c
類有四種不同的類型,但a
和b
只有一種類型與它們相關聯。
如果你預先知道多少type
是你要去檢查,並想在該類型存在的類別以顯示一個布爾值,你可以這樣做:
SELECT,
a.name,
b.id IS NOT NULL AS TypeA,
c.id IS NOT NULL AS TypeB,
-- etc...
FROM
category a
LEFT JOIN
types b ON a.type = b.id AND b.id = 1
LEFT JOIN
types c ON a.type = c.id AND c.id = 2
-- etc...
編輯:如果您不知道預先創建的列的數量,但仍然希望在各自的單獨列中爲每種類型設置布爾值,那麼另一種選擇是在應用程序邏輯中動態構建查詢字符串。假設您使用的是PHP例如:
$columns = $ljoins = array();
$i = 1;
foreach($pdo->query('SELECT id, name FROM types') as $row)
{
$columns[] = "t$i.id IS NOT NULL AS " . $row['name'];
$ljoins[] = "LEFT JOIN types t$i ON a.type = t$i.id AND t$i.id = " . $row['id'];
$i++;
}
$sql = 'SELECT a.name, ' . implode(', ', $columns) . ' FROM category a ' . implode(' ', $ljoins);
$stmt = $pdo->query($sql);
// Do stuff with result-set
那不是我要找的。我希望將類型顯示爲列。所以不是「類型」,我想顯示typea,typeb。我開始相信這是不可能的。 – Dani
是的,'PIVOT'僅適用於Oracle,SQL Server DBMS。你在開發你的應用程序是什麼?你實際上可以做的一件事是在你的應用程序邏輯中動態構建你的查詢。首先,您將查詢所有類型及其ID,然後使用該信息動態構建一個查詢字符串,然後將多個「LEFT JOIN」連接起來,因爲它們都有類型。通過這種方式,您並不是在查詢中對列選擇進行硬編碼,但它仍然是一個笨重的解決方案,如果在SQL中處理它會更好。 –
好的謝謝。不幸的是我使用mysql來獲取數據。 – Dani
我在這裏概述幾種情況。
首先,最直接的是:
SELECT c.name AS "CatName",
IF(typea.id IS NULL, 0, 1) AS "TypeA",
IF(typeb.id IS NULL, 0, 1) AS "TypeB"
FROM category c
LEFT JOIN types typea ON c.type = typea.id AND typea.name = 'TypeA'
LEFT JOIN types typeb ON c.type = typeb.id AND typeb.name = 'TypeB';
但這需要手動提的所有類型的查詢,這顯然不是你正在尋找的東西。
可以構建SQL查詢並使用它,此方法假定您正在從某個腳本運行查詢,該腳本可以從第一個查詢中獲取輸出並將其用作新查詢。
SELECT concat('SELECT c.name AS "CatName",',
group_concat(concat('IF(',lower(t.name),
'.id IS NULL,0,1) AS "',t.name,'"')),
' FROM category c ',
group_concat(concat('LEFT JOIN types ',
lower(t.name),' ON c.type = ',lower(t.name),'.id AND ',
lower(t.name),'.name = ''',t.name,'''') SEPARATOR ' '),
';')
FROM types t;
寫一個小的shell(或其他)腳本應該很容易。
在標準的SQL,不可能用表的內容來創建DML語句。不同的數據庫爲此提供了不同的功能,如PIVOT
語句,過程語言等。我不知道如何使用MySQL工具來實現此目的,但是這個想法是動態構建第2點中概述的查詢並執行它。
我已經介紹了關於該SQL Fiddle第2例。
您的第二個解決方案很有趣,因爲它就像我的PHP示例,它基於多少種類型動態構建查詢。我不知道這樣的東西是否可以合併到存儲過程中。 –
@ZaneBien,當然有可能。我不知道如何在MySQL中做到這一點,但PostgreSQL對我來說非常簡單。 – vyegorov
你知道有多少種(列),你會預先檢查呢?如果是這樣,你是否想顯示一個布爾型「0」或「1」,如果該類型存在的類別? –