Mysql行到列查询

时间:2013-06-06 14:57:20

标签: mysql function

我希望这是一个相对简单的问题。我有一个数据库表中的事务列表,我想将列中的枚举值(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,但这不是我真正想要实现的目标。

如果有人对如何实现这一目标有任何想法,那就太棒了。

一如既往地提前感谢。

干杯 格雷厄姆

4 个答案:

答案 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'))

该查询可能会受益于accCodevehichleManufacturer上的覆盖索引。

(这是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

非常感谢 格雷厄姆