2011-08-11 11 views
7

Potrzebuję wygenerować listę adresów, do których mój klient będzie wysyłać katalogi towarów. Chcą wysłać określoną liczbę katalogów (X) do określonego kodu pocztowego (Y) [To ma związek ze średnim dochodem w tych kodach pocztowych]Pobierz inną liczbę wierszy dla każdej kategorii z tabeli SQL Server

Mam 2 tabele w SQL Server 2008 R2: CatalogRequests i AddressList

CatalogRequests jest lista ilu katalogów powinniśmy wysłać do każdego kodu pocztowego w naszej bazie klientów:

| Zip | QuantityRequested | 
------------------------------- 
| 12345 |   150   | 
| 13445 |   800   | 
| 45678 |   200   | 
| 41871 |   350   | 
| 77777 |   125   | 

AddressList jest tak, że lista adresów =)

| Name |  Address1 | Address2 |  City  | State | Zip | 
--------------------------------------------------------------------------- 
| Bruce | 1 BatCave Dr |   | Gotham City | IL | 12345 | 
| Clark | 9 Smallville St | Apt A | Metropolis | NY | 45678 | 
| Thor | 5 Valhalla Way |   | Asgard  | ?? | 77777 | 

Przez pewien czas próbowałem zrobić to za pomocą zapytania SQL, po czym poddałem się i napisałem mały program w języku C#, który wykonał to, co było mi potrzebne (zasadniczo generując kilka zapytań SQL - po jednym dla każdego rekord w CatalogRequests).

Moje pytanie brzmi, jak mogłem to zrobić z jednym zapytaniem SQL? Jestem po prostu ciekawy w tym momencie, wydaje się, że jest sposób, aby to zrobić i po prostu coś mi brakuje. Lub może nie być możliwe i jestem szalony =)

Zestaw wyników będzie rekordami z AddressList, które spełniają wymagania w CatalogRequest (na przykład 150 rekordów z kodem pocztowym 12345, 800 rekordów z kodem pocztowym 13445 itd.).

+0

Dziękuję za laska! –

+0

Nie ma za co, @CodeMagician! Twoje rozwiązanie bardzo mi pomogło w tym czasie. Dodatkowo chciałem [kapelusz związany z nagrodami] (http://winterbash2014.stackexchange.com/) ;-) – jadarnel27

Odpowiedz

11

Hmm ... Co o coś takiego:

;with addressListWithID 
AS 
(
    SELECT name, address1, adress2, city, state, zip, 
      ROW_NUMBER() OVER(partition by zip order by newid()) as Row 
    FROM AddressList 
) 
SELECT A.name, A.address1, A.adress2, A.city, A.state, A.zip 
FROM addressListWithID A 
    INNER JOIN CatalogRequests C 
     ON C.zip = A.zip 
      AND A.row <= C.QuantityRequested 

losowe adresy w ilości wnioskowanej.

+0

Upewnij się, że umieściłeś kwalifikacje tabeli na liście wyboru ... 'zip' rzuci niejednoznaczny błąd nazwy pola. – JNK

+0

Dobry chwyt, dzięki! zapytanie zostało edytowane. –

+1

Może, tylko może, lepiej zastąpić 'A.row <= C.QuantityRequested' przez' A.row BETWEEN 1 AND C.QuantityRequested', ponieważ chodzi tu o filtrowanie wartości dyskretnych. –

4

Jednym ze sposobów jest wykorzystanie dynamicznego SQL (which is dangerous and not to be taken lightly):

DECLARE @SQL varchar(max) 

SET @SQL = 'USE Database' 

SELECT @SQL = @SQL + 'SELECT TOP ' 
      + QuantityRequired 
      + ' * FROM AddressList WHERE Zip = ' 
      + Zip 
      + ' UNION ALL' 
FROM CatalogRequests 

SET @SQL = LEFT(@SQL, (LEN(@SQL - 10))) -- remove last UNION ALL 

PRINT (@SQL) 

-- EXEC (@SQL) 

Sprawdź link do kanonicznej odniesienie dynamiczny SQL.

+0

+1 Bardzo fajnie! Jest to podobne do tego, co zrobił mój kod - zaoszczędziłoby mi to trochę czasu, wiedząc, że mogę to zrobić w SQL. Dzięki! – jadarnel27

5

Nietestowane, bo nie ma żadnych danych DDL i testy:

SELECT A.name , 
     A.address1 , 
     A.adress2 , 
     A.city , 
     A.[state] , 
     A.zip 
FROM CatalogRequests AS C 
     CROSS APPLY (SELECT TOP (C.QuantityRequested) 
           A.name , 
           A.address1 , 
           A.adress2 , 
           A.city , 
           A.[state] , 
           A.zip 
         FROM  addressListWithID AS A 
         WHERE  C.zip = A.zip 
        ) AS A 
+0

+1 Testowany i działa ... Nie wiedziałem, że było to możliwe dzięki "CROSS APPLY", świetnie wiedzieć! – James

+0

Zdecydowanie działa, dziękuję za odpowiedź! +1 za to, że jest nieco bardziej czytelny niż odpowiedź MagicMike – jadarnel27

Powiązane problemy