根据2列从同一列中选择多个值

时间:2013-04-25 10:40:47

标签: sql

最佳解释使用示例。我的试验和结果如下所示。

有两个表(实际上我有多个表)

表:产品

ID    name
-----------
1    apple
2    orange
3    pear

表:属性

ID  prod_ID   attr_id   value
----------------------------
1   1       101     20
2   1       102     red
3   1       103     sweet
4   2       101     30
5   2       102     orange
6   2       103     sour
6   3       101     40 
7   3       102     green
8   3       103     sweet

期望的输出

name   attr_id 101 AS 'price'   attr_id 102 AS 'taste'
------------------------------------------------------
apple        20           sweet
orange       30           sour
pear         40           sweet

到目前为止,我已经管理过SQL,但最近我不得不调用3个表并组合列值,如上所示。我只是无法把头包裹起来。非常感谢帮助。

4 个答案:

答案 0 :(得分:2)

由于您未在提问中提及任何RDBMS,因此下面的查询将适用于大多数RDBMS。

SELECT  a.Name,
        MAX(CASE WHEN b.attr_ID = 101 THEN b.value END) Price,
        MAX(CASE WHEN b.attr_ID = 103 THEN b.value END) Taste
FROM    Products a
        INNER JOIN Attributes b
            ON a.ID = b.prod_ID
GROUP   BY a.Name

答案 1 :(得分:1)

您可以使用CASE语句:(这将在MySQL中运行)

SELECT p.name
   ,GROUP_CONCAT(CASE WHEN attr_id = 101 THEN value else NULL END) AS price
   ,GROUP_CONCAT(CASE WHEN attr_id = 102 THEN value else NULL END) AS color
   ,GROUP_CONCAT(CASE WHEN attr_id = 103 THEN value else NULL END) AS taste
FROM Products p JOIN Attributes a
ON p.id = a.prod_id
GROUP BY p.name;

或者您也可以对join进行相同的操作:(这将在MySQL和SQL Server中都有效)

SELECT Name
  ,CASE WHEN a.attr_id = 101 THEN a.value ELSE NULL END AS price
  ,CASE WHEN b.attr_id = 102 THEN b.value else NULL END AS color
  ,CASE WHEN c.attr_id = 103 THEN c.value else NULL END AS taste
FROM Products p
  LEFT JOIN Attributes a ON p.id = a.prod_id
  LEFT JOIN Attributes b ON p.id = b.prod_id AND a.attr_id = 101 AND b.attr_id = 102
  LEFT JOIN Attributes c ON p.id = c.prod_id AND a.attr_id = 101 AND c.attr_id = 103
WHERE a.attr_id IS NOT NULL and b.attr_id IS NOT NULL AND c.attr_id IS NOT NULL

我还为color添加了一列。

输出

|   NAME | PRICE |  COLOR | TASTE |
-----------------------------------
|  apple |    20 |    red | sweet |
| orange |    30 | orange |  sour |
|   pear |    40 |  green | sweet |

See this SQLFiddle

Demo for SQL Server

答案 2 :(得分:0)

您必须分别查询每个列...

SELECT 
  p.name,
  (SELECT value FROM Attributes a WHERE attr_id=101 AND a.prod_ID=p.ID) AS price,
  (SELECT value FROM Attributes a WHERE attr_id=102 AND a.prod_ID=p.ID) AS taste
FROM Products p

......或...... 如果您使用的是MSSQL 2008 R2,则可以使用PIVOT: http://msdn.microsoft.com/en-us/library/ms177410(v=sql.105).aspx

答案 3 :(得分:0)

使用PIVOT,可以轻松调整其他属性。

SELECT NAME, [101],[102],[103]
             FROM (
                    SELECT P.NAME as NAME, A.ATTR_ID as ATTR_ID, A.VALUE as VALUE
                    FROM PRODUCTS as P, ATTRIBUTES as A
                    WHERE A.PROD_ID = P.ID  
             ) SrcTable
            PIVOT 
            (
                MAX(VALUE)
                for ATTR_ID in ([101],[102],[103])
            ) PivotTable;

或者可以生成动态语句来调整可变数量的属性(因为这是上面语句中唯一更改的内容)

列字符串可以通过类似以下方式获得:

DECLARE @columns AS NVARCHAR(MAX);
set @columns = STUFF((SELECT distinct ',' + QUOTENAME(ATTR_ID) 
             FROM ATTRIBUTES
             FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)'),1,1,'');

接下来,该变量可以用于生成类似于静态PIVOT的字符串

DECALARE @stmt AS NVARCHAR(MAX);
set @stmt ='SELECT NAME, ' + @columns + '
             FROM (
                    SELECT P.NAME as NAME, A.ATTR_ID as ATTR_ID, A.VALUE as VALUE 
                    FROM PRODUCTS as P, ATTRIBUTES as A 
                    WHERE A.PROD_ID = P.ID 
             ) SourceTable
             PIVOT ( 
                MAX(VALUE)
                for ATTR_ID in (' + @columns + ') 
            ) PivotTable';

EXECUTE(@stmt);