簡體   English   中英

基於2個表以及一個聯接表和行的MySQL查詢應按順序包括聯接數據的所有實例

[英]MySQL query based on 2 tables and a join table and rows should include all instances, in order, of joined data

我需要創建一個表結果(並找出在MySQL的約束范圍內是否可行),該結果將包含來自2個表的數據,但查詢本身將基於3個表(包括連接表)。 並將合並結果添加到輸出結果中。

表結構:

registrants
id, first name, last name, industryID

industries
id, name

registrants_industries (join table)
id, registrant_id, industry_id

因此,在最終輸出結果表中,任何注冊人都可以擁有0、1個或多個行業,這些行業名稱應加在最終結果表的末尾。

registrants.id, 
registrants.first_name, 
registrants.last_name, 
industry.name-1,      
industry.name-2,  
industry.name-3,  
industry.name-4,  
industry.name-5.

但是所有列都應按行業排列。 例如,如果有5個行業,則輸出將如下所示:

行業按以下順序排列:油漆,平鋪,一般建築,院子護理,屋頂)

354, Mike, Smith, Painting,’’,’’,Yard Care,’’
599, Joe, Jones, ‘’,’’,’General Construction’,’’,’’

因此,所有行業列將對齊並可以在Excel等中進行排序。

(My)SQL可以輸出此查詢嗎? 如果是這樣,您對最佳方法提出了什么好的建議?

我開始寫查詢,只是找不到答案來解決基於匹配項添加的列。 並根據需要將所有內容逐一匯總。

您可以使用子查詢為每個registrants_industries條目分配一個數字:

select  r.id, 
,       r.first_name
,       r.last_name
,       min(case when ri.RowNr = 1 then i.name end) as [Industry-1]
,       min(case when ri.RowNr = 2 then i.name end) as [Industry-2]
,       min(case when ri.RowNr = 3 then i.name end) as [Industry-3]
,       min(case when ri.RowNr = 4 then i.name end) as [Industry-4]
,       min(case when ri.RowNr = 5 then i.name end) as [Industry-5]
from    registrants r
join    (
        select  (
                select  count(*)
                from    registrants_industries ri3
                where   ri3.registrant = r2.registrant
                        and ri3.id <= ri2.id
                ) as RowNr
        ,       *
        from    registrants_industries ri2
        ) ri
on      ri.registrant_id = r.id
join    industries i
on      i.id = ri.industry_id
group by
        r.id
,       r.first_name
,       r.last_name

您可以使用group_concat並將所有行業放在同一列中。 我知道這並不是您所提問題的確切答案,但是這個答案很接近,而且我不相信只有3個聯接就可以提出您的要求。

SELECT
R.id, 
R.first_name, 
R.last_name, 
GROUP_CONCAT(I.name) AS industries
FROM registrants R
JOIN registrants_industries RI ON R.id = RI.registrant_id
JOIN industires I ON RI.industry_id = I.id
GROUP BY R.id

這將產生

354, Mike, Smith, "Painting,Yard Care"
599, Joe, Jones, "’General Construction’"

您要將值透視到相應的列中。 這是常見的要求,尤其是對於報告和導出到電子表格。

在SQL中,您需要在查詢中聲明列,並且在查詢有機會查看數據之前,它們在查詢准備時已固定。 您無法讓查詢根據查詢到的數據值自動向其結果集中動態添加列。

解決方法是對將包含在查詢結果中的每個不同值的表達式進行硬編碼

SELECT r.id, r.first_name, r.last_name,
  MAX(CASE i.name WHEN 'Painting' THEN i.name END) AS `Painting`,
  MAX(CASE i.name WHEN 'Tiling' THEN i.name END) AS `Tiling`,
  MAX(CASE i.name WHEN 'General Construction' THEN i.name END) AS `General Construction`,
  MAX(CASE i.name WHEN 'Yard Care' THEN i.name END) AS `Yard Care`,
  MAX(CASE i.name WHEN 'Roofing' THEN i.name END) AS `Roofing`
FROM registrants r
LEFT OUTER JOIN (
  registrants_industries ri
  INNER JOIN industries i ON i.id = ri.industry_id
) ON r.id = ri.registrant_id
GROUP BY r.id;

這意味着您要么需要知道數據中可能存在哪些不同的值,要么需要在運行以上查詢之前發現它們:

SELECT DISTINCT name FROM industries;

然后編寫應用程序代碼以使用該結果生成具有可變列數的SQL查詢字符串,其中一個列表達式與每個不同的行業名稱相對應。

另一種選擇是不使用SQL進行透視,而是取回原始數據回到您的應用程序,並按用戶ID取多個行,將結果排序到應用程序數據結構中,直到您擁有一些看起來像您想要的透視數據集的網格視圖為止。

如果要查詢適應數據並為存在的每個數據值返回一列,則需要一種或另一種方式編寫應用程序代碼。 您可以編寫代碼來預處理數據並生成SQL查詢,或者編寫代碼來對數據進行后處理。

暫無
暫無

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

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