簡體   English   中英

MYSQL 子查詢行作為主查詢中的列

[英]MYSQL Subquery Rows as Columns in Main Query

在我們的數據庫中,我們有一個用戶表和其他數據的鍵值表。 我們一直在嘗試提出一個將兩者連接起來的查詢,將 kv 表中的鍵作為列標題,將值作為字段。

目前我們唯一的解決方案是將每個用戶的鍵值對GROUP_CONCAT作為一列,然后在查詢輸出后解析它們——緩慢而糟糕......

這是一般設置:

User.db 表:

------------------------------
| uid | firstname | lastname |
------------------------------
| 01 | john       | doe      |
| 02 | jane       | doe      |
------------------------------

-----------------------------
| uid | question  |  answer |
-----------------------------
|  01 | question1 | answer1 |
|  01 | question2 | answer2 |
|  02 | question1 | answer3 |
|  02 | question2 | answer4 |
-----------------------------

我們想要得到的查詢結果:

------------------------------------------------------
| uid | firstname | lastname | question1 | question2 |
------------------------------------------------------
|  01 | john      | doe      | answer1   | answer2   |
|  02 | jane      | doe      | answer3   | answer4   |
------------------------------------------------------

我希望有一種直接的方法可以做到這一點,但一直找不到任何東西。 所有幫助將不勝感激。

在其他數據庫中,您可以使用PIVOT函數,但 MySQL 沒有該函數,因此必須使用聚合函數和CASE語句復制它。 如果您知道所有值,則可以對類似於以下內容的值進行硬編碼:

select u.uid, u.firstname, u.lastname,
  max(case when question='question1' then answer else null end) as question1,
  max(case when question='question2' then answer else null end) as question2
from users u 
left join kv 
  on u.uid = kv.uid
group by u.uid, u.firstname, u.lastname;

請參閱帶有演示的 SQL Fiddle

但是如果你有未知的值,那么你可以使用准備好的語句來生成動態 SQL:

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'max(case when question = ''',
      question,
      ''' then answer else NULL end) AS ',
      question
    )
  ) INTO @sql
FROM kv;

SET @sql = CONCAT('SELECT u.uid, u.firstname, u.lastname, ', @sql, ' 
                  from users u 
                  left join kv 
                    on u.uid = kv.uid 
                  group by u.uid, u.firstname, u.lastname');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

參見SQL Fiddle with Demo

兩個版本都會產生相同的結果:

| UID | FIRSTNAME | LASTNAME | QUESTION1 | QUESTION2 |
------------------------------------------------------
|   1 |      john |      doe |   answer1 |   answer2 |
|   2 |      jane |      doe |   answer3 |   answer4 |

准備好的語句的好處是,如果您有更改的值,那么這將在運行時生成列列表。

這將模擬 PIVOT 表:

Select
  uid,
  firstname,
  lastname,
  max(case when question = 'question1' then answer end) as question1,
  max(case when question = 'question2' then answer end) as question2
From
  users inner join answers on users.uid = answers.uid
Grop by uid, firstname, lastname

還有一個帶有連接的解決方案:

Select uid, firstname, lastname,
  answers_1.answer as question1,
  answers_2.answer as question2
From
  users left join answers answers_1
  on users.uid = answers_1.uid and answers_1.question = 'question1'
  left join answers answers_2
  on users.uid = answers_2.uid and answers_2.question = 'question2'

當然,你必須事先知道問題是什么。 如果情況並非如此,據我所知,由於 MySql 不支持 PIVOT,因此無法僅使用標准 SQL 來回答您的問題。

你可以嘗試這樣的事情:

select u.uid, u.firstname, u.lastname,
  max(case when question="question1" then answer else null) as question1,
  max(case when question="question2" then answer else null) as question2
from user u join answers a on u.uid = a.uid
group by u.uid, u.firstname, u.lastname

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM