sql查询交叉表

时间:2013-01-04 01:33:34

标签: mysql sql

我有一个包含以下表格的数据库:

customer_info表,包含以下列:

custID | storeName     | accName
  1    |  bayport      | name one
  2    |  plainfield   | name two
  3    |  bayport      | name three

使用以下列处理表:

dealID | dealDate     | custID
  1    | 2012-10-15   |   1
  2    | 2012-11-25   |   2
  3    | 2012-12-17   |   3
  4    | 2012-12-17   |   1

phone_details表,包含以下列

phone_ID  | instore  | online  | received | dealID  
    1     |    1     |    0    |    0     |   1
    2     |    1     |    0    |    0     |   1
    3     |    0     |    1    |    1     |   1    
    4     |    0     |    1    |    0     |   2
    5     |    0     |    1    |    0     |   3
    6     |    0     |    1    |    1     |   3
    7     |    1     |    0    |    1     |   4
    8     |    1     |    0    |    1     |   4

invoice_details

payment_ID   | due  | paid | tender | dealID
      1      | 1000 | 500  | cash   |    1    
      2      | 500  | 100  | credit |    2 
      3      | 200  | 200  | cash   |    3 
      4      | 350  | 350  | debit  |    4

如何查询此表格,以便我的结果在特定日期看起来像这样?

例如,2012-10-15 - 2012-11-25它看起来像这样

               | bayport |   plainfield 
# of instore   |    2    |       0
# of online    |    1    |       1
total          |    3    |       1
# of received  |    1    |       0
total amount   |  1000   |      500

2 个答案:

答案 0 :(得分:3)

@MichaelBerkowski's excellent answer形成鲜明对比的是,如果你能够容忍以bayport / plainfield为导向的数据作为行,并且在店内/在线作为列(每个my comment以上),你可以简单地做:

SELECT    c.storeName,
          SUM(p.instore) AS `# of instore`,
          SUM(p.online ) AS `# of online`
FROM      customer_info c
LEFT JOIN deals         d
       ON d.custID    = c.custID
      AND d.dealDate  = '2012-10-15'
LEFT JOIN phone_details p USING (dealID)
GROUP BY  storeName

sqlfiddle上查看。

答案 1 :(得分:2)

这绝对是一个奇怪的配置。

这需要UNION ALL,它会抓取每个onlineinstore值,使其成为行而不是列。然后使用SUM(CASE...)将其转换为将商店名称转换为列。

SELECT 
  calltype,
  /* In the outer query, pivot the storeName */
  SUM(CASE WHEN storeName = 'bayport' THEN num ELSE 0 END) AS bayport,
  SUM(CASE WHEN storeName = 'plainfield' THEN num ELSE 0 END) AS plainfield
FROM (
    /* First half gets the instore */
    SELECT
      /* String literal for label column */
      '# of instore' AS calltype,
      COUNT(*) AS num,
      storeName
    FROM
      customer_info c
      LEFT JOIN deals d ON c.custID = d.custID
      LEFT JOIN phone_details p ON d.dealID = p.dealID
    WHERE instore = 1 AND dealDate = '2012-10-15'
    GROUP BY storeName, calltype
    UNION ALL
    /* Second half gets the online */
    SELECT
      '# of online' AS calltype,
      SUM(online) AS num,
      storeName
    FROM
      customer_info c
      LEFT JOIN deals d ON c.custID = d.custID
      LEFT JOIN phone_details p ON d.dealID = p.dealID
    WHERE online = 1 AND dealDate = '2012-10-15'
    GROUP BY storeName, calltype
) totals 
GROUP BY calltype, storeName

http://sqlfiddle.com/#!2/af18b/13