2012-04-10 15 views
5

समेकित खाता हैंडलिंग सेट करने के लिए, मैं उन खातों को जानना चाहता हूं जो में मालिकों का "बिल्कुल वही" सेट है।रिकॉर्ड्स के अन्य समूहों से मेल खाने वाले रिकॉर्ड के समूह (रिलेशनल डिवीजन?)

मुझे लगता है कि यह मालिकों को गतिशील एसक्यूएल के साथ पिटोट करने के लिए काम कर सकता है, फिर रैंकिंग फ़ंक्शंस का उपयोग करें, लेकिन मैं उस दृष्टिकोण को आगे नहीं लेना चाहता; मुझे पर कोई ऊपरी सीमा नहीं है कि दिए गए खाते से कितने नाम जुड़े जा सकते हैं, इसलिए मैं गतिशील एसक्यूएल से बचना चाहता हूं।

मेरे डेटा (भी इस http://www.sqlfiddle.com/#!3/1d36e पर है)

CREATE TABLE allacctRels 
(account INT NOT NULL, 
module CHAR(3) NOT NULL, 
custCode CHAR(20) NOT NULL) 


INSERT INTO allacctrels 
(account, module, custCode) 
VALUES 
(1, 'DDA', 'Wilkie, Walker'), 
(1, 'DDA', 'Houzemeal, Juvy'), 
(2, 'CDS', 'Chase, Billy'), 
(2, 'CDS', 'Norman, Storm'), 
(3, 'CDS', 'Chase, Billy'), 
(3, 'CDS', 'Norman, Storm'), 
(7, 'CDS', 'Perkins, Tony'), 
(15, 'SVG', 'Wilkie, Walker'), --typo in name before mwigdahl's response 
(16, 'SVG', 'Wilkie, Walker'), -- corrected typo here too 
(606, 'DDA', 'Norman, Storm'), 
(606, 'DDA', 'Chase, Billy'),-- corrected 2nd typo found 
(4, 'LNS', 'Wilkie, Walker'), 
(4, 'LNS', 'Houzemeal, Juvy'), 
(44, 'DDA', 'Perkins, Tony'), 
(222, 'DDA', 'Wilkie, Walker'), 
(222, 'DDA', 'Houzemeal, Juvy'), 
(17, 'SVG', 'Wilkie, Walker'), -- added these three rows in edit, SVG 17 doesn't match any dda 
(17, 'SVG', 'Welch, Raquel'), 
(17, 'SVG', 'Houzemeal, Juvy') 

मैं पता लगाना चाहते हैं, प्रत्येक मॉड्यूल-खाता, क्या सबसे कम डीडीए खाता है कि ठीक उसी मालिकों इसके साथ जुड़े है के लिए।

नमूना डेटा में, मैं इन परिणामों को चाहता हूं, तीसरा कॉलम निम्नतम डीडीए खाता है जिसमें एक ही मालिक हैं। में प्रत्येक पंक्ति के प्रति एक पंक्ति "DISTINCT मॉड्यूल का चयन करें, allAcctRels से खाता")

1, DDA, 1 
2, CDS, 606 
3, CDS, 606 
15, SVG, NULL 
16, SVG, NULL 
606, DDA, 606 
4, LNS, 1 
7, CDS, 44 
44, DDA, 44 
222, DDA, 1 
17, SVG, NULL -- added to original post. 

एसवीजी 15 और 16 के डीडीए से मेल नहीं खाते - परिणाम thereâ फिर से मॉड्यूल/खाता कॉम्बो के रूप में पंक्तियों की संख्या समान होना चाहिए खाता, इसलिए इससे कोई फर्क नहीं पड़ता कि वे एक दूसरे से मेल खाते हैं, खाते को समेकित करने के लिए उन्हें न्यूल मिलता है। संपादित करें: एसवीजी 17 कुछ भी मेल नहीं खाता है, भले ही एक डीडीए एक्ट है जिसमें एसवीजी 17 में अपने सभी धारक हैं, एसवीजी 17 में धारकों का संयोजन किसी भी डीडीए एक्ट के लिए नहीं होता है। प्रत्येक डीडीए खाता स्वयं से मेल खाता है, जब तक कि डीडीए खाते एक ही मालिक के साथ नहीं है और कम डीडीए मौजूद है (जैसा कि डीडीए 222 के मामले में है)।

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

ऐसा लगता है कि यह एक "रिलेशनशिप डिवीजन" समस्या है, संबंधपरक विभाजन शायद क्रॉस आवेदन द्वारा "खिलाया" जा रहा है। मैंने को एक फ़ंक्शन लिखने की कोशिश की जो खाताधारकों की एक तालिका से संबंधित एक विशिष्ट खाते के साथ ले लेती है और नीचे दिखाए गए के साथ सबसे कम डीडीए खाता ढूंढती है, यह विचार यह देखने के लिए होता है कि दिए गए में सभी लोगों की संख्या खाता उन लोगों की संख्या के समान होता है जब वह खाता किसी दिए गए डीडीए खाते में शामिल हो जाता है, लेकिन मैं यह नहीं समझ सकता कि फ़ंक्शन में खाता संख्याओं को "फ़ीड" कैसे करें।

-- this is what I tried but I'm not sure it the logic would work 
-- and I can't figure out how to pass the account holders for each 
-- account in. This is a bit changed from the function I wrote, some 
    -- extraneous fields removed and cryptic column names changed. So it 
    -- probably won't run as is. 

    -- to support a parameter type to a tape 
-- CREATE type VisionCustomer as Table 
-- (customer varchar(30)) 

CREATE FUNCTION consolidatable 
(@custList dbo.VisionCustomer READONLY) 
RETURNS char(10) 
AS 
BEGIN 
DECLARE @retval Varchar(10) 
DECLARE @howmany int 
select @howmany=Count(*) FROM @custlist; 

SELECT @retval = min (acct) FROM allAcctRels 
    JOIN @custlist 
     On VendorCustNo = Customer 
      WHERE acctType = 'DDA' 
      GROUP BY acct 
      HAVING (count(*) = @howmany) 
      and 
      COUNT(*) = (select Count(*) FROM allAcctRels X 
    WHERE X.acctType = 'DDA' 
    AND X.account = AllAcctRels.account) ; 
RETURN @retval 
END; 
+0

ध्यान दें कि "चेस, बिली" 606 डीडीए पंक्ति में resultset के साथ हंसी नहीं है कि आप कहते हैं कि तुम वापस चाहते हैं ; मुझे लगता है कि आप इसे "चेस, बिली" होना चाहते हैं, है ना? – mwigdahl

+0

हां, यह सही है, इसके बारे में खेद है, और धन्यवाद, मैं अब –

उत्तर

1

यह वास्तव में बहुत सरल लगता है, अगर मैं आपको सही ढंग से समझता हूं। इसे आज़माएं:

SELECT a.account, a.module, MIN(b.account) 
FROM allacctRels a 
    LEFT JOIN allacctRels b ON a.custCode = b.custCode AND b.module = 'DDA' 
GROUP BY a.account, a.module 

संपादित करें: उपर्युक्त स्पष्टीकरण के बाद काम नहीं करता है, लेकिन यह चाहिए। यह वास्तव में एक प्रकार का संबंधपरक विभाजन है। शायद दुनिया में सबसे कुशल क्वेरी योजना नहीं है, लेकिन यह काम करता है।

SELECT a.account, a.module, MIN(b.account) 
FROM allacctRels a 
    LEFT JOIN allacctRels b ON b.module = 'DDA' 
    AND 
    -- first test is to confirm that the number of matching names for this combination equals the number of names for the DDA set... 
    (
     SELECT COUNT(*) 
     FROM allacctRels b2 
      INNER JOIN allacctRels a2 ON b2.custCode = a2.custCode 
     WHERE a.account = a2.account AND b.account = b2.account 
    ) = 
    (
     SELECT COUNT(*) 
     FROM allacctRels b2 
     WHERE b.account = b2.account 
    ) 
    AND 
    -- second test is to confirm that the number of names for the DDA set equals the number of names for the base set... 
    (
     SELECT COUNT(*) 
     FROM allacctRels b2 
     WHERE b.account = b2.account 
    ) = 
    (
     SELECT COUNT(*) 
     FROM allacctRels a2 
     WHERE a.account = a2.account 
    ) 
GROUP BY a.account, a.module 
+0

+1 फिर से संपादित कर दूंगा; यह पहली चीज है जो मेरे सिर में चली गई जब मैं इसे देख रहा था। – lyrisey

+0

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

+0

स्पष्टीकरण के लिए धन्यवाद। मैं इसे फिर से देख रहा हूँ। – mwigdahl

1

मुझे इस पर विश्वास है आप (http://www.sqlfiddle.com/#!3/f96c5/1) के लिए क्या देख रहे:

;WITH AccountsWithOwners AS 
(
    SELECT DISTINCT 
    DA.module 
    , DA.account 
    , STUFF((SELECT 
       ',' + AAR.custCode 
       FROM allacctRels AAR 
       WHERE AAR.module = DA.module 
       AND AAR.account = DA.account 
       ORDER BY AAR.custCode 
       FOR XML PATH('')) 
       , 1, 1, '') AS Result 
    FROM allacctRels DA 
) 
, WithLowestDda AS 
(
    SELECT 
     AWO.module 
     , AWO.account 
     , MatchingAccounts.account AS DdaAccount 
     , ROW_NUMBER() OVER(PARTITION BY AWO.module, AWO.account ORDER BY MatchingAccounts.account) AS Row 
    FROM AccountsWithOwners AWO 
    LEFT JOIN AccountsWithOwners MatchingAccounts 
     ON MatchingAccounts.module = 'DDA' 
     AND MatchingAccounts.Result = AWO.Result 
) 
SELECT 
    account 
    , module 
    , DdaAccount 
FROM WithLowestDda 
WHERE Row = 1 
+0

यह एक विजेता की तरह दिखता है, जैसे ही मुझे कुछ बैकअप और सिर घर शुरू करना है, मैं इसे आज रात देखता हूं लेकिन मुझे लगता है कि यह मेरे परीक्षण डेटा पर सही परिणाम प्राप्त करता है। मैं फॉर एक्सएमएल से परिचित नहीं हूं, इसलिए मैं यह जानना चाहता हूं कि यह स्वीकार करने से पहले कैसे काम करता है। –

+0

@ लेविन मैग्राउडर यह मूल रूप से एक्सएमएल बना रहा है जिसमें कोई वास्तविक मार्कअप नहीं है और इसका उपयोग अल्पविराम से अलग सूची बनाने के लिए किया जाता है। अगर आपका कोई प्रश्न हैं, तो मुझे से पूछें। –

संबंधित मुद्दे