2011-08-11 9 views
7

Necesito generar una lista de direcciones a las que mi cliente va a enviar catálogos de mercancías. Quieren enviar un cierto número de catálogos (X) a un código postal particular (Y) [Esto tiene que ver con el ingreso promedio en esos códigos postales]Recuperar un número diferente de filas para cada categoría desde la tabla de SQL Server

Tengo 2 tablas en SQL Server 2008 R2: CatalogRequests y AddressList

CatalogRequests es una lista del número de catálogos que deberíamos enviar a cada código postal en nuestra base de datos de clientes:

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

AddressList es sólo eso, una lista de direcciones =)

| 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 | 

Me sacudí el cerebro por un tiempo tratando de hacer esto con una consulta SQL, luego desistí y escribí un pequeño programa C# para hacer lo que tenía que hacer (básicamente, generar un montón de consultas SQL, una para cada registro en CatalogRequests).

Mi pregunta es, ¿cómo podría haber hecho esto con una consulta SQL? Tengo curiosidad en este punto, parece que hay una manera de hacerlo y me falta algo. O podría no ser posible y estoy loco =)

El conjunto de resultados sería registros de AddressList que cumplían los requisitos en CatalogRequest (por ejemplo, 150 registros con un código postal de 12345, 800 registros con un código postal de 13445, etc.).

+0

Gracias por la generosidad! –

+0

De nada, @CodeMagician! Tu solución realmente me ayudó en ese momento. Además, quería [el sombrero relacionado con recompensas] (http://winterbash2014.stackexchange.com/) ;-) – jadarnel27

Respuesta

11

Hmm ... ¿Qué pasa algo como esto:

;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 

direcciones aleatorias en la cantidad solicitada.

+0

Asegúrese de poner las calificaciones de la tabla en su lista de selección ... 'zip' arrojará un error de nombre de campo ambiguo. – JNK

+0

¡Buena captura, gracias! consulta ha sido editada. –

+1

Tal vez, solo tal vez, sería mejor reemplazar 'A.row <= C.QuantityRequested' con' A.row BETWEEN 1 AND C.QuantityRequested', ya que se trata de filtrar valores discretos. –

4

Un método consiste en utilizar SQL dinámico (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) 

Comprobar el enlace para la referencia canónica de SQL dinámico.

+0

+1 ¡Muy bueno! Esto es similar a lo que hizo mi código: esto me habría ahorrado algo de tiempo sabiendo que podría hacerlo en SQL. ¡Gracias! – jadarnel27

5

No comprobado, porque no hay ninguna DDL y datos de prueba:

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 Probado y funciona ... No sabía que esto fuera posible con 'CROSS APPLY', ¡es genial saberlo! – James

+0

Definitivamente funciona, gracias por la respuesta! +1 para este ser un poco más legible que la respuesta de MagicMike – jadarnel27

Cuestiones relacionadas