我知道这很复杂,但我真诚地希望有人能检查一下。 我做了短版(为了更好地理解问题)和完整版(用原始SQL)
[TABLE A] [TABLE B]
|1|a|b| |1|x
|2|c|d| |1|y
|3| | | |2|z
|5| | | |2|v
|4|w
如何让MySQL查询以获得类似的行:
1|a|b|x|y
2|c|d|z|v
A中有2列,B中有2列作为列,只有键1和2,没有空结果
子查询?
我试图从Prestashop db 连续获取:
很容易获得id_product,ean13和upc,因为它是ps_product表中的一行。为了获得我使用子查询的功能(JOIN没有用)。
所以,我选择了id_product,ean13,upc,(subquery1)作为code1,(subquery2)作为code2。 然后我需要抛出空行。但不能只将code1或code2放在WHERE中。 为了使它工作,我不得不把所有东西放在子查询中。
此代码 WORKS ,但它非常难看,我打赌这应该以不同的方式完成。
如何才能更好?
SELECT * FROM(
SELECT
p.id_product as idp, p.ean13 as ean13, p.upc as upc, (
SELECT
fvl.value
FROM
`ps_feature_product` fp
LEFT JOIN
`ps_feature_value_lang` fvl ON (fp.id_feature_value = fvl.id_feature_value)
WHERE fp.id_feature = 24 AND fp.id_product = idp
) AS code1, (
SELECT
fvl.value
FROM
`ps_feature_product` fp
LEFT JOIN
`ps_feature_value_lang` fvl ON (fp.id_feature_value = fvl.id_feature_value)
WHERE fp.id_feature = 25 AND fp.id_product = idp
) AS code2,
m.name
FROM
`ps_product` p
LEFT JOIN
`ps_manufacturer` m ON (p.id_manufacturer = m.id_manufacturer)
) mainq
WHERE
ean13 != '' OR upc != '' OR code1 IS NOT NULL OR code2 IS NOT NULL
答案 0 :(得分:2)
create table tablea
( id int,
col1 varchar(1),
col2 varchar(1));
create table tableb
( id int,
feature int,
cola varchar(1));
insert into tablea (id, col1, col2)
select 1,'a','b' union
select 2,'c','d' union
select 3,null,null union
select 5,null,null;
insert into tableb (id, feature, cola)
select 1,24,'x' union
select 1,25,'y' union
select 2,24,'z' union
select 2,25,'v' union
select 4,24,'w';
select a.id, a.col1, a.col2, b1.cola b1a, b2.cola b2a
from tablea a
inner join tableb b1 on (b1.id = a.id and b1.feature = 24)
inner join tableb b2 on (b2.id = a.id and b2.feature = 25);
SQLFiddle here。
答案 1 :(得分:0)
您想要做的是Pivot Query。 MySQL没有本地支持数据透视查询,但其他RDBMSen也支持。
您可以使用派生列模拟数据透视查询,但必须指定每个派生列。也就是说,MySQL本身不可能使列数与另一个表的行匹配。这必须提前知道。
将结果作为行查询然后使用PHP进行聚合会更容易。例如:
while ($row = $result->fetch()) {
if (!isset($table[$row->id])) {
$table[$row->id] = array();
}
$table[$row->id][] = $row->feature;
答案 2 :(得分:0)
这不是一个简单的问题,因为它不是标准查询,顺便说一句,如果您可以使用视图,则可以执行以下过程。假设你是从这些表开始的:
CREATE TABLE `A` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`firstA` char(1) NOT NULL DEFAULT '',
`secondA` char(1) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
);
CREATE TABLE `B` (
`id` int(11) unsigned NOT NULL,
`firstB` char(1) NOT NULL DEFAULT ''
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `A` (`id`, `firstA`, `secondA`)
VALUES (1, 'a', 'b'), (2, 'c', 'd');
INSERT INTO `B` (`id`, `firstB`)
VALUES (1, 'x'), (1, 'y'), (2, 'z'), (2, 'v'), (4, 'w');
首先创建一个连接两个表的视图:
create or replace view C_join as
select A.firstA, A.secondA, B.firstB
from A
join B on B.id=A.id;
创建对表B中的行进行分组的视图:
create or replace view d_group_concat as
select firstA, secondA, group_concat(firstB) groupconcat
from c_join
group by firstA, secondA
创建满足您需求的视图:
create or replace view e_result as
select firstA, secondA, SUBSTRING_INDEX(groupconcat,',',1) firstB, SUBSTRING_INDEX(SUBSTRING_INDEX(groupconcat,',',2),',',-1) secondB
from d_group_concat
就是这样。希望这会对你有所帮助。
如果您无法创建视图,则可能是查询:
select firstA, secondA, SUBSTRING_INDEX(groupconcat,',',1) firstB, SUBSTRING_INDEX(SUBSTRING_INDEX(groupconcat,',',2),',',-1) secondB
from (
select firstA, secondA, group_concat(firstB) groupconcat
from (
select A.firstA, A.secondA, B.firstB
from A
join B on B.id=A.id
) c_join
group by firstA, secondA
) d_group_concat
答案 3 :(得分:0)
非常感谢大家的答案。马克的答案是第一个,最简单,在我的案例中完美无缺。使用子查询,查询运行速度比我的快几倍。谢谢,马克!
我只需要说几句话:
它是Prestashop和批发交换平台的集成组件的一部分。批发商在平台上使用4种产品代码系统(ean13,upc和2个其他系统)。这两个其他产品代码在Prestashop中作为产品功能添加。该商店有数千种产品,平台上有数十万种产品。这就是速度至关重要的原因。
以下是我的问题的完整版的代码。也许有人会觉得这很有帮助。
查询将Prestashop产品代码和某些功能放在一行:
SELECT
p.id_product, p.ean13, p.upc, fvl1.value as code1, fvl2.value as code2
FROM `ps_product` p
LEFT JOIN
`ps_feature_product` fp1 ON (p.id_product = fp1.id_product and fp1.id_feature = 24)
LEFT JOIN
`ps_feature_value_lang` fvl1 ON (fvl1.id_feature_value = fp1.id_feature_value)
LEFT JOIN
`ps_feature_product` fp2 ON (p.id_product = fp2.id_product and fp2.id_feature = 25)
LEFT JOIN
`ps_feature_value_lang` fvl2 ON (fvl2.id_feature_value = fp2.id_feature_value)
WHERE
ean13 != '' OR upc != '' OR fvl1.value IS NOT NULL OR fvl2.value IS NOT NULL;