简体   繁体   English

sql查询交叉表

[英]sql query cross tab

I have a db with the following tables: 我有一个带有以下表格的数据库:

customer_info table with the following columns: 带以下各列的customer_info表:

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

deals table with the following columns: 带有以下各列的Deals表:

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 table with the following columns 具有以下各列的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

How can I query this table so that my result will look like this for a certain date? 如何查询该表,以便在特定日期我的结果看起来像这样?

For example, 2012-10-15 - 2012-11-25 it would look like this 例如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

Just to contrast with @MichaelBerkowski's excellent answer , if you could tolerate the data oriented with bayport/plainfield as rows and instore/online as columns (per my comment above), you can simply do: 与@MichaelBerkowski 的出色回答相反,如果您可以容忍以Bayport / plainfield为行,以instore / online为列的数据(根据上面的评论 ),则可以执行以下操作:

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

See it on sqlfiddle . sqlfiddle上看到它。

This is definitely an odd configuration. 这绝对是一个奇怪的配置。

This will require a UNION ALL which grabs the online and instore values for each to make them into rows rather than columns. 这将需要一个UNION ALL其抓住onlineinstore值为每个使他们成为行而不是列。 That is then pivoted using a SUM(CASE...) to turn the store names into columns. 然后使用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 http://sqlfiddle.com/#!2/af18b/13

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM