簡體   English   中英

SQL查詢表中所有可能的組合

[英]SQL query for all possible combinations from table

我有一張表是SQL數據庫的一些計算結果,它看起來像這樣:

[ID] [PAR1] [PAR2]
[A]   [110]  [0.5]
[B]   [105]  [1.5]
[C]   [120]  [2.0]
[D]   [130]  [3.0]
[E]   [115]  [5.5]
[F]   [130]  [6.5]
[G]   [120]  [7.0]
[H]   [110]  [7.5]
[I]   [105]  [8.0]
[J]   [120]  [9.0]
[K]   [110]  [9.5]

按PAR2排序-更少意味着更好的結果。 我需要從3行中找到SUM PAR2的最佳結果,其中PAR1的總和至少為350(至少為350)。 例如:

  • A + B + C的組合給出的總和PAR2的最佳結果(0.5 + 1.5 + 2.0 = 4.0),但是PAR1的總和:110 + 105 + 120 = 335 <(350)-條件不正常,不能使用結果,
  • A + B + D的組合給出了總和PAR2的結果(0.5 + 1.5 + 3.0 = 5.0),但是PAR1的總和:110 + 105 + 130 = 345 <(350)-條件不正確,無法使用結果
  • A + B + E的組合給出了總和PAR2的結果(0.5 + 1.5 + 5.5 = 7.5),但是PAR1的總和:110 + 105 + 115 = 330 <(350)-條件不正確,無法使用結果
  • A + B + F的組合給出的結果為PAR2之和(0.5 + 1.5 + 6.5 = 8.5),但是PAR1之和:110 + 105 + 130 = 345 <(350)-條件不正確,不能使用結果( ...)
  • B + C + D的組合得出的總和為PAR2(1.5 + 2.0 + 3.0 = 6.5),而PAR1的總和為:105 + 120 + 130 = 355>(350)- 條件尚可!最好的結果6.5

這是一個ASP.NET應用程序,因此我嘗試從數據庫中獲取表並在后面使用VB代碼來獲取結果,但這是使用FOR..NEXT LOOP的“手動”工作,需要一些時間。 因此,對於這樣的計算而言,這不是一個很好的選擇,而且太慢了。

我想知道是否有更好的平滑和智能的SQL代碼可以直接從SQL查詢獲得結果。 也許一些高級數學功能? 有任何想法嗎?

提前致謝。


我使用forpas解決方案進行了一些測試,是的,它的效果非常好。 但是當我添加很多WHERE條件時需要花費很多時間,因為原始表非常大。 因此,我將嘗試找到在函數(而非過程)中使用臨時表的解決方案。 謝謝大家的答案。

forpas,特別感謝您提供示例和解釋,通過這種方式,您可以讓我快速地了解您的想法-這是大師級別的;)

您可以像這樣使用雙重內部自聯接:

select top 1 * from tablename t1
inner join tablename t2 on t2.id > t1.id
inner join tablename t3 on t3.id > t2.id
where t1.par1 + t2.par1 + t3.par1 >= 350
order by t1.par2 + t2.par2 + t3.par2

參見演示
結果:

> ID | PAR1 | PAR2 | ID | PAR1 | PAR2 | ID | PAR1 | PAR2
> :- | ---: | :--- | :- | ---: | :--- | :- | ---: | :---
> A  |  110 | 0.5  | C  |  120 | 2.0  | D  |  130 | 3.0 

因此獲勝者是A + C + D,因為:

110 + 120 + 130 = 360 >= 350 

PAR2之和為

0.5 + 2.0 + 3.0 = 5.5

最小的

檢查一下。 我覺得它准確或接近您的要求-

WITH CTE (ID,PAR1,PAR2)
AS
(
    SELECT 'A',110,0.5  UNION ALL
    SELECT 'B',105,1.5  UNION ALL
    SELECT 'C',120,2.0  UNION ALL
    SELECT 'D',130,3.0  UNION ALL
    SELECT 'E',115,5.5  UNION ALL
    SELECT 'F',130,6.5  UNION ALL
    SELECT 'G',120,7.0  UNION ALL
    SELECT 'H',110,7.5  UNION ALL
    SELECT 'I',105,8.0  UNION ALL
    SELECT 'J',120,9.0  UNION ALL
    SELECT 'K',110,9.5
)
SELECT B.AID,B.BID,B.CID,SUM_P2,SUM_P1
(
    SELECT * , ROW_NUMBER() OVER (PARTITION BY CHAR_SUM ORDER BY CHAR_SUM) CS
    FROM 
    (
        SELECT ASCII(A.ID) + ASCII(B.ID)+ASCII(C.ID) CHAR_SUM,
        A.ID AID,B.ID BID,C.ID CID,
        (A.PAR2+B.PAR2+C.PAR2) AS SUM_P2,
        (A.PAR1+B.PAR1+C.PAR1) AS SUM_P1
        FROM CTE A
        CROSS APPLY CTE B
        CROSS APPLY CTE C
        WHERE A.ID <> B.ID AND A.ID <> C.ID AND B.ID <> C.ID
        AND (A.PAR1+B.PAR1+C.PAR1) >= 350
    ) A
)B
WHERE CS = 1

您可以嘗試將表自身交叉連接三遍。 這樣,您將可以將三行的所有組合樞轉到單個行,從而使您能夠應用所需的條件並選擇最大值。

select  t1.ID, t2.ID, t3.ID, t1.PAR2 + t2.PAR2 + t3.PAR2
from    yourTable t1
cross join
        yourTable t2
cross join
        yourTable t3
where   t1.ID < t2.ID and t2.ID < t3.ID and
        t1.PAR1 + t2.PAR1 + t3.PAR1 >= 350
order by t1.PAR2 + t2.PAR2 + t3.PAR2 ASC

盡管此解決方案在技術上應該可行,但交叉連接表並不是理想的性能,甚至多次執行時也是如此。 如果表的大小將隨着時間增長,並且您可以選擇在代碼級應用計算,那么我認為這樣做是明智的。

編輯

更改了where子句,包括Serg的建議

暫無
暫無

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

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