我希望这是一个相对简单的问题。我有一个数据库表中的事务列表,我想将列中的枚举值(y / n)提取到该表中存在的每个摩托车制造商。
我尝试了以下查询:
SELECT
accCode,
rnFuncBool(accCode,'HON') purchasedHonda,
rnFuncBool(accCode,'YAM') purchasedYamaha,
rnFuncBool(accCode,'KAW') purchasedKawsaki,
rnFuncBool(accCode,'SUZ') purchasedSuzuki,
rnFuncBool(accCode,'DUC') purchasedDucati,
rnFuncBool(accCode,'KTM') purchasedKTM,
rnFuncBool(accCode,'SYM') purchasedSym,
rnFuncBool(accCode,'VIC') purchasedVictory
FROM _emarsys_vehiclessold WHERE accCode<>'' GROUP BY accCode
和函数rnFuncBool如下:
DELIMITER $$
USE `phcontacts`$$
DROP FUNCTION IF EXISTS `rnFuncBool`$$
CREATE DEFINER=`root`@`localhost` FUNCTION `rnFuncBool`(
fnAccCode VARCHAR(6),
fnAccMan VARCHAR(3)
) RETURNS VARCHAR(1) CHARSET utf8
BEGIN
IF (SELECT COUNT(*) FROM _emarsys_vehiclessold WHERE accCode=fnAccCode COLLATE utf8_unicode_ci AND vehichleManufacturer=fnAccMan COLLATE utf8_unicode_ci )>0 THEN
RETURN 'y';
ELSE
RETURN 'n';
END IF;
END$$
DELIMITER ;
虽然这似乎是一个非常合理的快速返回解决方案,但主表包含超过48,000行,因此执行时间以分钟为单位。
我确实尝试在临时表上使用联接,但只有在按客户帐户代码分组时才返回一个制造商。
当然我可以尝试group_concat,但这不是我真正想要实现的目标。
如果有人对如何实现这一目标有任何想法,那就太棒了。
一如既往地提前感谢。
干杯 格雷厄姆
答案 0 :(得分:2)
如果你选择布尔值1/0而不是y / n,那么你可以大大简化自己的事情,并做一个更有效的交叉表问题查询......
SELECT
accCode,
SUM(CASE WHEN accCode ='HON' THEN 1 ELSE 0 END) purchasedHonda,
SUM(CASE WHEN accCode='YAM' THEN 1 ELSE 0 END) purchasedYamaha,
...
SUM(CASE WHEN accCode='VIC' THEN 1 ELSE 0 END) purchasedVictory
FROM _emarsys_vehiclessold WHERE accCode<>''
GROUP BY accCode
话虽这么说,你的代码以及我所显示的简要修正案是按照accCode进行分组,这就是你所说的你想要的,但是我不确定你有多大价值,除非你'重新构建一个查找表或类似的东西,在这种情况下,您可以简单地获取一个不同的accCode列表,并手动或在Excel中完成其余操作,就像编写SQL一样快。
答案 1 :(得分:2)
每当你在设计中得到这样的“循环”时,通常会有更高效的设计。
很难弄清楚为什么你需要一个udf,以及为什么它会查询同一个表,以及为什么该查询需要为表中的每一行执行8次(或者更确切地说,每行都是accCode&lt;&gt; ; '')。如果48,000行与该外部查询中的条件匹配,那么将对该函数进行384,000次调用,这将是针对数据库执行的总共384,001次查询。
我无法理解为什么你需要这样做,以获得指定的结果集。
只需一次通过表格就可以获得更有效的信息,查询类似于:
SELECT accCode
, MAX(IF(vehichleManufacturer='HON','y','n')) AS purchasedHonda
, MAX(IF(vehichleManufacturer='YAM','y','n')) AS purchasedYamaha
, MAX(IF(vehichleManufacturer='KAW','y','n')) AS purchasedKawasaki
, ...
FROM _emarsys_vehiclessold
WHERE accCode<>''
GROUP
BY accCode
您的功能包括一个规范,比较应该是不区分大小写的排序规则。如果需要指定,可以在SQL
中完成 , MAX(IF(vehichleManufacturer='HON' COLLATE utf8_unicode_ci,'y','n'))
该查询可能会受益于accCode
和vehichleManufacturer
上的覆盖索引。
(这是vehichleManufacturer
列名称的奇怪拼写。)
特定于MySQL的IF()
函数可以替换为等效的ANSI CASE
表达式,例如:
, MAX(CASE WHEN vehichleManufacturer='HON' THEN 'y' ELSE 'n' END)
答案 2 :(得分:0)
尝试:
SELECT accCode,
case sum(CASE accCode WHEN 'HON' THEN 1 ELSE 0 END)
when 0 then 'n' else 'y'
end purchasedHonda,
case sum(CASE accCode WHEN 'YAM' THEN 1 ELSE 0 END)
when 0 then 'n' else 'y'
end purchasedYamaha,
case sum(CASE accCode WHEN 'KAW' THEN 1 ELSE 0 END)
when 0 then 'n' else 'y'
end purchasedKawsaki,
case sum(CASE accCode WHEN 'SUZ' THEN 1 ELSE 0 END)
when 0 then 'n' else 'y'
end purchasedSuzuki,
case sum(CASE accCode WHEN 'DUC' THEN 1 ELSE 0 END)
when 0 then 'n' else 'y'
end purchasedDucati,
case sum(CASE accCode WHEN 'KTM' THEN 1 ELSE 0 END)
when 0 then 'n' else 'y'
end purchasedKTM,
case sum(CASE accCode WHEN 'SYM' THEN 1 ELSE 0 END)
when 0 then 'n' else 'y'
end purchasedSym,
case sum(CASE accCode WHEN 'VIC' THEN 1 ELSE 0 END)
when 0 then 'n' else 'y'
end purchasedVictory
FROM _emarsys_vehiclessold WHERE accCode<>'' GROUP BY accCode
答案 3 :(得分:0)
非常感谢Steph对此的帮助。要说明数据正在导出到CSV文件以供外部使用,因此导入的系统只需要一个平面文件。
我已稍微修改了您的查询,并且它可以正常运行:
SELECT accCode,
(IF (SUM(CASE WHEN `vehichleManufacturer` ='HON' THEN 1 ELSE 0 END)>0,'y','n')) purchasedHonda,
(IF (SUM(CASE WHEN `vehichleManufacturer` ='KAW' THEN 1 ELSE 0 END)>0,'y','n')) purchasedKawasaki,
(IF (SUM(CASE WHEN `vehichleManufacturer` ='SUZ' THEN 1 ELSE 0 END)>0,'y','n')) purchasedSuzuki,
(IF (SUM(CASE WHEN `vehichleManufacturer` ='DUC' THEN 1 ELSE 0 END)>0,'y','n')) purchasedDucati,
(IF (SUM(CASE WHEN `vehichleManufacturer` ='KTM' THEN 1 ELSE 0 END)>0,'y','n')) purchasedKTM,
(IF (SUM(CASE WHEN `vehichleManufacturer` ='SYM' THEN 1 ELSE 0 END)>0,'y','n')) purchasedSym,
(IF (SUM(CASE WHEN `vehichleManufacturer`='YAM' THEN 1 ELSE 0 END)>0,'y','n')) purchasedYamaha,
(IF (SUM(CASE WHEN `vehichleManufacturer`='VIC' THEN 1 ELSE 0 END)>0,'y','n')) purchasedVictory
FROM _emarsys_vehiclessold WHERE accCode<>''
GROUP BY accCode
非常感谢 格雷厄姆