2017-04-14 67 views
2
+----------+---------+---------+-----------+-----------+--------------+ 
| entry_id | item_id | stat_id | stat_type | int_value | string_value | 
+----------+---------+---------+-----------+-----------+--------------+ 
|  1 | 4255 |  10 | int  |  54 | NULL   | 
|  2 | 4255 |  16 | int  |  443 | NULL   | 
|  3 | 4255 |  56 | int  |  13 | NULL   | 
|  4 | 6544 |  10 | int  |  54 | NULL   | 
|  5 | 6544 |  56 | int  |  13 | NULL   | 
|  6 | 6544 |  16 | int  |  443 | NULL   | 
|  7 | 8570 |  56 | int  |  13 | NULL   | 
|  8 | 8570 |  10 | int  |  76 | NULL   | 
|  9 | 8570 |  72 | int  |   1 | NULL   | 
+----------+---------+---------+-----------+-----------+--------------+ 

以上是我擁有的表格的示例。 任務是爲表提供一個目標「item_id」值,獲取與目標具有相同行的「item_id」。使用MySQL查詢查找具有匹配行的ID

在上面的示例中,提供4255的「item_id」將返回6544,在這兩個「item_id」值都在三行中找到,每行另有匹配(除「entry_id」之外)。

實質上,我需要找出數據庫中是否存在另一個「item_id」,即在所有方面與目標相同。如果它具有相同的行,但也可以在其他行中找到,則不會將其歸類爲匹配項。

作爲SQL查詢的一部分,可以做這種事情嗎? 我目前正在C#代碼中執行此操作,其中我逐一查看包含目標「item_id」的每一行,查找匹配項。這看起來效率很低。

+0

這不僅是一個有趣的問題,但它是相當的網站上的第一個問題寫得很好的。 –

回答

0

假設您沒有重複項(組合(item_id, stat_id, stat_type, int_value, string_value)是唯一的)並且只有string_value可以爲NULL,那麼您可以連接完全匹配並比較行計數(mathces的數量必須等於兩者的行數項目)。

select t2.item_id 
from t t1 
join t t2 using(stat_id, stat_type, int_value) 
where t1.item_id = 4255 
    and t2.item_id <> t1.item_id 
    and t2.string_value <=> t1.string_value 
group by t1.item_id, t2.item_id 
having count(*) = (select count(*) from t where t.item_id = 4255) 
    and count(*) = (select count(*) from t where t.item_id = t2.item_id) 

演示:http://rextester.com/RIU87596

0

我認爲MySQL中最簡單的方法是使用group_concat()。這是一個黑客的一點點,但它應該很好地工作 - 假設你可以用NULL一點點靈活:

select t.item_id 
from (select item_id, 
      group_concat(stat_id, '|', stat_type, '|', int_value, '|', coalesce(string_value, '<NULL>' order by stat_id) as fields 
     from t 
     group by item_id 
    ) t join 
    (select item_id, 
      group_concat(stat_id, '|', stat_type, '|', int_value, '|', coalesce(string_value, '<NULL>' order by stat_id) as fields 
     from t 
     where item_id = 4255 
    ) tspecial 
    on tspecial.fields = t.fields; 

注意事項:

  • 這需要一些特殊處理NULL
  • 默認情況下,用於group_concat()的內部字符串的長度爲1,024個字符。如果需要,這可以被覆蓋。
  • 這假定這些字段沒有分隔字符('|')。

關係解決方案有點複雜。

select i.item_id 
from (select distinct item_id from t) i cross join 
    (select stat_id, stat_type, int_value, string_value 
     from t where item_id = 4255 
    ) s left join 
    t 
    on t.stat_id = s.stat_id and 
     t.stat_type = s.stat_type and 
     t.int_value is not distinct from s.int_value and 
     t.string_value is not distinct from s.string_value 
group by i.item_id 
having count(*) = count(t.stat_id); 

這是如何工作的?它會爲所有項目所需的字段生成所有統計數據。然後它執行left join以匹配其他字段中的值。聚合然後檢查匹配統計數量與預期數量匹配。

其中一個優點是該版本對NULL值或分隔符不具有奇怪的限制。