在MySQL中,如何从一个表中获得2列,从另一表中获得2行作为另一表的列?

问题描述 投票:5回答:4

我知道这很复杂,但是我衷心希望有人能检查一下。我制作了短版(以更好地理解问题)和完整版(使用原始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数据库中获取一行

  • 产品ID
  • ean13代码
  • upc代码
  • 具有ID 24的功能
  • 具有ID 25的功能

很容易获得id_product,ean13和upc,因为它是ps_product表中的一行。为了获得功能,我使用了子查询(JOIN无法解决)。

因此,我选择id_product,ean13,upc,(subquery1)作为代码1,(subquery2)作为代码2。然后我需要扔掉空白行。但是不能只是将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
php mysql sql subquery prestashop
4个回答
3
投票
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


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;

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

0
投票

非常感谢大家的回答。 James的回答是最简单,最简单的方法,在我看来,这种方法非常有效。带有子查询的查询运行速度比我的快几倍。谢谢,詹姆斯!

只需几句话,为什么我需要它:

这是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;
© www.soinside.com 2019 - 2024. All rights reserved.