2012-07-13 19 views
6

मेरे पास चालान और क्रेडिट कार्ड लेन-देन के बीच कई से अधिक रिश्ते हैं, जिन्हें मैं एक साथ रकम मैप करने की कोशिश कर रहा हूं। समस्या के बारे में सोचने का सबसे अच्छा तरीका एक द्विपक्षीय ग्राफ के रूप में TransactionInvoiceMap कल्पना करना है। प्रत्येक जुड़े सबग्राफ के लिए, सभी चालानों के कुल और उस सबग्राफ के सभी लेनदेन के कुल खोजें। मेरी पूछताछ में, मैं इनमें से प्रत्येक उप-अनुच्छेद के साथ गणना किए गए मानों को वापस लेनदेन आईडी के साथ वापस करना चाहता हूं। संबंधित लेनदेन के लिए कुल समान होना चाहिए।मैं कई से कई मैपिंग टेबल में डेटा के लॉजिकल सबसेट को कुशलता से कैसे बना सकता हूं?

अधिक स्पष्ट रूप से, निम्नलिखित लेनदेन दिया/चालान

Table: TransactionInvoiceMap 
TransactionID InvoiceID 
1    1 
2    2 
3    2 
3    3 

Table: Transactions 
TransactionID Amount 
1    $100 
2    $75 
3    $75 

Table: Invoices 
InvoiceID Amount 
1   $100 
2   $100 
3   $50 

मेरी वांछित आउटपुट

TransactionID TotalAsscTransactions TotalAsscInvoiced 
1    $100     $100 
2    $150     $150 
3    $150     $150 

नोट चालान कि 2 और 3 और लेन-देन 2 और 3 एक तार्किक समूह का हिस्सा हैं है।

यहां एक समाधान (सरलीकृत, नाम बदल गया) है जो स्पष्ट रूप से काम करता है, लेकिन बहुत धीमा है। मुझे यह समझने में कठिनाई हो रही है कि इसे कैसे अनुकूलित किया जाए, लेकिन मुझे लगता है कि इसमें ट्रांज़ेक्शनइनोइस ग्रुपिंग में सबक्वायरी को समाप्त करना शामिल होगा। कुछ मूल रूप से अलग सुझाव देने के लिए स्वतंत्र महसूस करें।

with TransactionInvoiceGrouping as (
    select 
     -- Need an identifier for each logical group of transactions/invoices, use 
     -- one of the transaction ids for this. 
     m.TransactionID, 
     m.InvoiceID, 
     min(m.TransactionID) over (partition by m.InvoiceID) as GroupingID 
    from TransactionInvoiceMap m 
) 
select distinct 
    g.TransactionID, 
    istat.InvoiceSum as TotalAsscInvoiced, 
    tstat.TransactionSum as TotalAsscTransactions 
from TransactionInvoiceGrouping g 
    cross apply (
     select sum(ii.Amount) as InvoiceSum 
     from (select distinct InvoiceID, GroupingID from TransactionInvoiceGrouping) ig 
      inner join Invoices ii on ig.InvoiceID = ii.InvoiceID 
     where ig.GroupingID = g.GroupingID 
    ) as istat 
    cross apply (
     select sum(it.Amount) as TransactionSum 
     from (select distinct TransactionID, GroupingID from TransactionInvoiceGrouping) ig 
      left join Transactions it on ig.TransactionID = it.TransactionID 
     where ig.GroupingID = g.GroupingID 
     having sum(it.Amount) > 0 
    ) as tstat 
+0

वे समूहबद्ध हैं क्योंकि वे सभी एक-दूसरे को "स्पर्श" करते हैं। यदि आपने प्रत्येक संबंध के लिए रेखाएं खींची हैं, तो चार ऑब्जेक्ट्स को कवर करने वाला ग्राफ होगा। मैंने सोचा कि इस तरह के समूह के लिए एक मैथी नाम था, लेकिन मुझे याद नहीं है। –

+0

@ स्टुअर्टब्रानन - तो, ​​उन्हें समूहीकृत किया गया है क्योंकि उनके पास एक आम चालान है ?, यह है कि यह कैसे काम करता है? और केवल यही कारण है कि आप कुल लेनदेन राशि के रूप में $ 150 जोड़ रहे हैं, क्योंकि आप लेनदेन 2 और लेनदेन 3 से राशि जोड़ रहे हैं? – Lamak

+0

हां, या यदि कोई आम लेनदेन है। ग्राफ रूपक इसे समझाने के लिए सबसे अच्छा काम करता है। क्या आपने पिछली टिप्पणी लिखी थी जिसे मैंने जवाब दिया था? शायद टिप्पणियां रखने के लिए एक अच्छा विचार है ताकि वे बाद के पाठकों के लिए समझ में आ जाए। –

उत्तर

2

मैं एक recursive CTE में समाधान को क्रियान्वित किया है:

;with TranGroup as (
    select TransactionID 
     , InvoiceID as NextInvoice 
     , TransactionID as RelatedTransaction 
     , cast(TransactionID as varchar(8000)) as TransactionChain 
    from TransactionInvoiceMap 
    union all 
    select g.TransactionID 
     , m1.InvoiceID 
     , m.TransactionID 
     , g.TransactionChain + ',' + cast(m.TransactionID as varchar(11)) 
    from TranGroup g 
     join TransactionInvoiceMap m on g.NextInvoice = m.InvoiceID 
     join TransactionInvoiceMap m1 on m.TransactionID = m1.TransactionID 
    where ',' + g.TransactionChain + ',' not like '%,' + cast(m.TransactionID as varchar(11)) + ',%' 
) 
, RelatedTrans as (
    select distinct TransactionID, RelatedTransaction 
    from TranGroup 
) 
, RelatedInv as (
    select distinct TransactionID, NextInvoice as RelatedInvoice 
    from TranGroup 
) 
select TransactionID 
    , (
     select sum(Amount) 
     from Transactions 
     where TransactionID in (
      select RelatedTransaction 
      from RelatedTrans 
      where TransactionID = t.TransactionID 
     ) 
    ) as TotalAsscTransactions 
    , (
     select sum(Amount) 
     from Invoices 
     where InvoiceID in (
      select RelatedInvoice 
      from RelatedInv 
      where TransactionID = t.TransactionID 
     ) 
    ) as TotalAsscInvoiced 
from Transactions t 

शायद अनुकूलन (! वस्तु मेरी ओर से नामकरण सहित) के लिए कुछ जगह नहीं है, लेकिन मेरा मानना ​​है कि मैं कम से कम एक सही समाधान है जो गणना में शामिल करने के लिए सभी संभावित लेनदेन-चालान संबंधों को इकट्ठा करेगा।

मैं ओपी के वांछित आउटपुट देने के लिए इस पृष्ठ पर मौजूदा समाधान प्राप्त करने में असमर्थ था, और वे अधिक परीक्षण डेटा जोड़ते हुए उलझन में थे। मुझे यकीन नहीं है कि क्या ओपी का पोस्ट "धीमा" समाधान सही है जैसा कि कहा गया है। यह बहुत संभव है कि मैं इस सवाल का गलत व्याख्या कर रहा हूं।

अतिरिक्त जानकारी:

मैं अक्सर देखा है पुनरावर्ती प्रश्नों धीमी गति से जब डेटा के बड़े सेट के साथ काम हो सकता है। शायद यह एक और एसओ सवाल का विषय हो सकता है। यदि ऐसा है, तो एसक्यूएल पक्ष पर कोशिश करने वाली चीजें सीमा को सीमित करने के लिए हो सकती हैं (where क्लॉज जोड़ें), इंडेक्स बेस टेबल, पहले एक अस्थायी तालिका में सीटीई का चयन करें, टेम्पलेट टेबल को इंडेक्स करें, एक बेहतर स्टॉप स्थिति के बारे में सोचें सीटीई ... लेकिन निश्चित रूप से प्रोफाइल, पहले।

+0

अजीब, मुझे पोस्ट की गई क्वेरी के साथ भी गलत परिणाम मिल गए हैं। मैंने इसे गलत तरीके से सरलीकृत कर दिया होगा। टेबल वैरिएबल पर इसे आजमाने के लिए एक सबक है। ;) आपको बताएगा कि यह आपके कोड के साथ कैसे जाता है। –

+0

इसके साथ खेलने के बाद, आपका समाधान वर्तमान में हमारे पास जितना अधिक सही लगता है। यह अभी भी वास्तव में धीमा है, लेकिन मुझे लगता है कि फ्रंटवे पर कुछ ट्वीकिंग और यूआई परिवर्तन इसे काम कर सकते हैं। मैं बाद में अंतिम समाधान के साथ इस उत्तर को अद्यतन करूंगा। रिकर्सिव सीटीई आपके सिर को पाने के लिए वास्तव में कठिन हैं। > _> –

+0

मुझे खुशी है कि यह आपको शुरू कर दिया है। मैंने इसे सुधारने के लिए कुछ संभावनाएं जोड़ दी हैं। अपना अंतिम उत्तर देखने के लिए इंतजार नहीं कर सकता, और मैं स्वीकार + बक्षीस की सराहना करता हूं। –

0

मैं सही सवाल को समझ लिया है, तो मुझे लगता है कि आप प्रत्येक चालान के लिए लेन-देन आईडी की न्यूनतम खोजने की कोशिश कर रहे हैं और मैं रैंकिंग समारोह का इस्तेमाल किया है भी ऐसा ही करने के लिए।

WITH TransactionInvoiceGrouping AS (
SELECT 
    -- Need an identifier for each logical group of transactions/invoices, use 
    -- one of the transaction ids for this. 
    m.TransactionID, 
    m.InvoiceID,  
    ROW_NUMBER() OVER (PARTITION BY m.InvoiceID ORDER BY m.TransactionID) AS recno 
FROM TransactionInvoiceMap m 
) 
SELECT 
g.TransactionID, 
istat.InvoiceSum AS TotalAsscInvoiced, 
tstat.TransactionSum AS TotalAsscTransactions 
FROM TransactionInvoiceGrouping g 
CROSS APPLY(
    SELECT SUM(ii.Amount) AS InvoiceSum 
    FROM TransactionInvoiceGrouping ig 
     inner JOIN Invoices ii ON ig.InvoiceID = ii.InvoiceID 
    WHERE ig.TransactionID = g.TransactionID 
    AND ig.recno = 1 
) AS istat 
CROSS APPLY(
    SELECT sum(it.Amount) AS TransactionSum 
    FROM TransactionInvoiceGrouping ig 
     LEFT JOIN transactions it ON ig.TransactionID = it.TransactionID 
    WHERE ig.TransactionID = g.TransactionID 
    AND ig.recno = 1 
    HAVING SUM(it.Amount) > 0 
) AS tstat 

WHERE g.recno = 1 
संबंधित मुद्दे