我有一个SQL查询,给出正确的结果,但执行速度太慢。
该查询对以下三个表进行操作:
customers
包含许多客户数据,例如姓名,地址,电话等。为简化表格,我仅使用名称。
customdatas
包含某些自定义(而非客户)数据。(表是用软件创建的,这就是为什么该表的复数形式是错误的)
customercustomdatarels
将自定义数据与客户相关联。
顾客
Id Name (many more columns)
-----------------------------------------------------------------------
8053c6f4c5c5c631054ddb13d9186117 MyCustomer ...
2efd2aa5711ddfade1f829b12dd88cf3 CheeseFactory ...
自订资料
id key
-------------------------------------------------
22deb172c1af6e8e245634a751871564 favoritsport
86eea84d296df9309ad6ff36fd7f856e favoritcheese
customercustomdatarels (客户数据和自定义数据之间的关系-具有相应的值)
customer customdata value
-------------------------------------------------------------------------------------
8053c6f4c5c5c631054ddb13d9186117 22deb172c1af6e8e245634a751871564 cycling
8053c6f4c5c5c631054ddb13d9186117 86eea84d296df9309ad6ff36fd7f856e cheddar
2efd2aa5711ddfade1f829b12dd88cf3 22deb172c1af6e8e245634a751871564 football
2efd2aa5711ddfade1f829b12dd88cf3 86eea84d296df9309ad6ff36fd7f856e mouldy
我想要的是一个基本上由所有数据组成的表,该表中包含customers
数量可变的额外列,对应于中指定的自定义数据customercustomdatarels
。这些列应在某处定义,因此我创建了下表,该表定义了这些额外的列并将它们映射到customdata
表中的键:
test_customkeymapping
colkey customkey
---------------------
1 favoritsport
2 favoritcheese
结果应为:
Name ExtraColumn_1 ExtraColumn_2
---------------------------------------------
CheeseFactory football mouldy
MyCustomer cycling cheddar
( ExtraColumn_1 因此是一个客户代名词最喜欢的运动和 ExtraColumn_2 是一个客户的代名词骄子奶酪。)
通过执行以下查询可以实现此结果:
SET @sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT('MAX(CASE
WHEN ckm.colkey = ', colkey, ' THEN
(SELECT value FROM customercustomdatarels ccdr2
LEFT JOIN customdatas cd2
ON cd2.id = ccdr2.customdata
WHERE cd2.key = ckm.customkey AND c.Id = ccdr2.customer)
END) AS ', CONCAT('`ExtraColumn_', colkey, '`'))
) INTO @sql
FROM test_customkeymapping;
SET @sql = CONCAT('SELECT c.Name, ', @sql, '
FROM customers c
LEFT JOIN customercustomdatarels ccdr
ON c.Id = ccdr.customer
LEFT JOIN customdatas cd
ON cd.Id = ccdr.customdata
LEFT JOIN test_customkeymapping ckm
ON cd.key = ckm.customkey
GROUP BY c.Id');
PREPARE stmt FROM @sql;
EXECUTE stmt;
这行得通。但是太慢了(对于7000个客户,它需要约10秒的时间)。该查询在很大程度上受以下问题的解决方案的影响:
MySQL将多行作为列连接
如何优化此查询?
我不明白您为什么在group_concat()
语句中使用子查询。这不会生成您真正想要运行的代码吗?
SET @sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT('MAX(CASE WHEN ckm.colkey = ', colkey, ' THEN ccd.value END) AS ',
CONCAT('ExtraColumn_', colkey, ''))
) INTO @sql
FROM test_customkeymapping;
SET @sql = CONCAT('SELECT c.Name, ', @sql, '
FROM customers c
LEFT JOIN customercustomdatarels ccdr
ON c.Id = ccdr.customer
LEFT JOIN customdatas cd
ON cd.Id = ccdr.customdata
LEFT JOIN test_customkeymapping ckm
ON cd.key = ckm.customkey
GROUP BY c.Id');
PREPARE stmt FROM @sql;
EXECUTE stmt;
注意:这未经测试,但是想法是相同的。在工作中使用mainfrom
语句中的值,而不要使用一些多余的,不必要的子查询中的值。
问题内容: 我在C#方面非常有经验,但是仍然还是SQL的初学者。 我们有一个使用MSSQL数据库的C#应用程序。 我们的应用程序的一部分只是简单地编写一系列预查询,作为报告,通过简单地运行查询并将返回的表粘贴到gridView即可显示该报告。用户正在请求一个新的报表,我不能完全确定仅使用SQL还是可以的,并且需要对返回的数据进行处理才能使其看起来正确。 用户想要的数据(以他们希望的方式呈现)将
问题内容: 我有一张桌子,我在其中存储合同的交易,如下所示: 用户应该能够选择查询的时间跨度,我要归档的是,如果用户从01/2012-03-2012中选择一个时间跨度,他会得到结果: 您对我有什么建议吗? 最好的问候,r3try 编辑:非常感谢您的答复!当我搜寻我的问题时,我也偶然发现了旋转问题,但是到目前为止,我还没有找到一个可以真正解决我的问题的示例(因为基本上每个示例都为列条目提供了特定的可
问题内容: 我有这样的桌子 由此,我需要创建一个临时表或类似这样的表: 有什么办法可以做到这一点吗? 问题答案: 检查这个小提琴 如果您确实想在其余部分中使用NULL值,则可以尝试以下操作: 这是新的小提琴 这是代码:
问题内容: 我有以下SQL问题: 如何使用SELECT命令将一列(内部文本)划分为两个单独的带有拆分文本的列? 我需要使用空格字符分隔文本数据。我知道最好举一个例子来简化它。所以: 输出: 所需的输出: 谢谢大家的帮助。 问题答案: 取决于数据的一致性-假设要在第一列与第二列中显示的内容之间用一个空格隔开: 您还可以在REGEX中使用以下查询: Oracle 10g +具有正则表达式支持,根据您需
问题内容: 我们有些SQL杂语。说我有一个看起来像这样的结果… 61E77D90-D53D-4E2E-A09E-9D6F012EB59C | A 61E77D90-D53D-4E2E-A09E-9D6F012EB59C | B 61E77D90-D53D-4E2E-A09E-9D6F012EB59C | C 61E77D90-D53D-4E2E-A09E-9D6F012EB59C | D 7ce9
问题内容: 请帮我这个: 我想按列TestType分组,但如果它们具有相同的TestType,则应将Result拆分为colunms 我希望SQL以这种格式返回数据 Result#列应该是动态的,因为每个TestType都有很多结果 问题答案: 正如我在评论中所提到的,这里您需要的是或交叉标签;我更喜欢后者,所以我将要使用的东西。 对此的非动态解决方案如下: 但是,问题在于这会将您“锁定”到3个结