我有两张桌子:
table 1
id item itemType
-----------------------
1 book1 1
2 book2 1
3 laptop1 2
table 2
id itemId name value
------------------------------------------
1 1 author enid blyton
2 1 title five 1
3 2 author enid blyton
4 2 title five 2
5 3 cpu i7-940
6 3 ram 4 GB
7 3 vcard nvidia quadro
当我使用过滤器itemType = 1查询时,结果应为:
query 1
id item author title
--------------------------------------------------------
1 book1 enid blyton five 1
2 book2 enid blyton five 2
并使用过滤器itemType = 2
query 2
id item cpu ram vcard
----------------------------------------------
1 laptop1 i7-940 4 GB nvidia quadro
且没有过滤器
query 3
id item author title cpu ram vcard
---------------------------------------------------------------------------
1 book1 enid blyton five 1
2 book2 enid blyton five 2
1 laptop1 i7-940 4 GB nvidia quadro
我使用表2的原因是因为每个itemType的参数都是在飞行期间创建的,因此不可能有像查询3中那样的表。
此时我可以通过以编程方式重建表(使用大量的linq调用)来解决这个问题。表1(1K行)和2(10K行)的小尺寸,性能良好,但现在表1的大小已超过100K行,表2超过1M行,性能非常好低。
是否有任何使用SQL查询的函数可以解决这个问题?
答案 0 :(得分:1)
不完全是动态的,但如果您的名字都是预先知道的,则可以使用PIVOT来检索您的数据。
PIVOT通过转动唯一值来旋转表值表达式 从表达式中的一列到输出中的多个列, 并在任何剩余的情况下执行聚合 最终输出中需要的列值。
SELECT t1.Id
, t1.item
, t2.author
, t2.title
, t2.cpu
, t2.ram
, t2.vcard
FROM table1 t1
INNER JOIN (
SELECT *
FROM (
SELECT itemId
, name
, value
FROM table2
) s
PIVOT (
MAX(Value)
FOR name IN (title, author, cpu, ram, vcard)
) p
) t2 ON t2.itemId = t1.Id
;WITH table1 (id, item, itemtype) AS (
SELECT 1, 'book1', 1
UNION ALL SELECT 2, 'book2', 1
UNION ALL SELECT 3, 'laptop1', 2
)
, table2 (id, itemId, name, value) AS (
SELECT 1, 1, 'author', 'enid blyton'
UNION ALL SELECT 2, 1, 'title', 'five 1'
UNION ALL SELECT 3, 2, 'author', 'enid blyton'
UNION ALL SELECT 4, 2, 'title', 'five 2'
UNION ALL SELECT 5, 3, 'cpu', 'i7 940'
UNION ALL SELECT 6, 3, 'ram', '4 GB'
UNION ALL SELECT 7, 3, 'vcard', 'nvidia quadro'
)
SELECT t1.Id
, t1.item
, t2.author
, t2.title
, t2.cpu
, t2.ram
, t2.vcard
FROM table1 t1
INNER JOIN (
SELECT *
FROM (
SELECT itemId
, name
, value
FROM table2
) s
PIVOT (
MAX(Value)
FOR name IN (title, author, cpu, ram, vcard)
) p
) t2 ON t2.itemId = t1.Id
答案 1 :(得分:1)
我建议运行一个查询,从table2返回指定itemtype的所有可能名称,如下所示:
select distinct name
from table2 t2
where exists (select null
from table1 t1
where t1.itemtype = @itemtype and
t1.id = t2.item_id)
在C#中,将名称连接成一个以逗号分隔的字符串,然后构造一个类似于Lieven答案的新查询字符串,如下所示:
SELECT t1.item
, t2.*
FROM table1 t1
INNER JOIN (SELECT *
FROM (SELECT itemId,
name,
value
FROM table2) s
PIVOT (MAX(Value)
FOR name IN (/*insert names string here*/)) p
) t2 ON t2.itemId = t1.Id
WHERE t1.itemtype = @itemtype;
(使用名称字符串替换括号内的注释)。
顺便说一下,如果可能的话,我建议将表2中的名称分成单独的查找表,如下所示:
name_table
----------
name_id
name
itemtype
- 这意味着第一个查询只需要查询一个小的查找表而不是查询表2;它也可以用于数据输入时名称值的一致性。