Salida de columna variable
Frecuentes
Visto 1,629 veces
-1
¿Puedo usar un bucle para crear un número variable de columnas en función de un cálculo?
Tabla A: tiene columnas id, nombre, fecha, artículo. Muestra quién compró un artículo en qué día. El nombre aparece varias veces cada vez que se compra un artículo. la identificación es única.
Tabla B: tiene nombre, fecha de inicio. Muestra cuando el nombre comenzó a funcionar.
(Sé cómo asociar el nombre con la fecha de inicio, por lo que no está realmente en el pseudocódigo a continuación).
La tabla C es como quiero que se vean mis resultados:
name itemsday1 itemsday2 itemsday3... itemsdayn
la segunda columna corresponde a artículos comprados hoy, la última columna a artículos comprados antes de la fecha de inicio del nombre. El número de columnas debe variar según la persona que comenzó primero. Quiero que mi consulta haga un bucle y cree una columna para cada día desde la fecha de inicio hasta hoy, donde cuente la cantidad de artículos comprados por Nombre ese día.
Código Psuedo:
declare mostd INT
select datediff(dd, begindate, getdate()) as spans into #span from B
set mostd = select max(spans) from #span
select
name
,while mostd !=0
begin
case when???
count(items)
end as column.mostd
mostd=mostd-1
end
end
from A (join B blah blah)
group by name
Results
NAME column4 column3 column2 column1 column0
James 9 8 7 6 NULL
Wade 5 4 3 NULL NULL
Bosh 2 1 NULL NULL NULL
Durant 0 9 8 NULL NULL
¿Puede TSQL hacer esto? ¿Puedes ayudarme a solidificar esto en código real? Gracias.
3 Respuestas
0
Necesitará usar SQL dinámico para hacer esto. Empezar con
DECLARE @SelectSQL varchar(max) = "SELECT name";
Luego haga su bucle while, rastreando un contador de enteros para el nombre del campo (si realmente quiere hacer esto en orden inverso, necesitará usar DATEDIFF(day, getdate(), begindate) y contar hacia atrás). Para cada día que desee que represente una columna, genere lo siguiente:
SELECT @SelectSQL = @SelectSQL + ', (SELECT COUNT(id) FROM TableA where name = TableB.name AND [date] = ''' + CONVERT(varchar, @mostd) + ''') AS column' + str(@ColumnCounter)
Luego, fuera del bucle, pospone el resto de la consulta:
@SelectSQL = @SelectSQL + ' FROM TableB';
Tenga en cuenta que no se unirá a TableA porque todo eso se soluciona en las subconsultas. Además, por la misma razón, no necesita GROUP BY.
Edit: Vaya, se me olvidó la última parte.
Para ejecutar esto, simplemente ejecute:
EXEC (@SelectSQL);
Respondido el 12 de junio de 12 a las 20:06
0
Esto es posible usando el operador PIVOT http://msdn.microsoft.com/en-us/library/ms177410(v=sql.105).aspx
ACTUALIZACIÓN: Un ejemplo. Está inspirado en este gran artículo: http://dotnetgalactics.wordpress.com/2009/10/23/using-sql-server-20052008-pivot-on-unknown-number-of-columns-dynamic-pivot/:
-- create table #items (id int, name varchar(40), date datetime, userid int)
-- create table #users (id int, name varchar(40), begindate datetime)
declare @dates varchar(4000)
declare @query varchar(4000)
SELECT @dates = STUFF(( SELECT DISTINCT
'],[' + cast(date as varchar(30))
FROM #items
ORDER BY '],[' + cast(date as varchar(30))
FOR XML PATH('')
), 1, 2, '') + ']'
set @query = 'SELECT * FROM (SELECT #users.name, date FROM #items
INNER JOIN #users ON #items.userid = #users.id) items
PIVOT (COUNT(date) FOR date IN (' + @dates + ')) pvt'
EXECUTE(@query)
Resultado:
name 2012-10-01 2012-10-02 2012-10-03 2012-10-04 2012-10-05 2012-10-06 2012-10-07
user1 0 0 1 0 0 1 0
user2 1 6 0 0 0 1 1
user3 1 1 7 0 0 3 0
user4 0 0 0 1 1 1 1
Respondido el 12 de junio de 12 a las 21:06
¿Podrías ayudarme a visualizar esto? ¿Está diciendo que un PIVOT en mi tabla original (Tabla A: id, nombre, fecha, artículo) puede rotar para hacer c columnas para cada día, filas para el nombre y agregados donde se encuentran? Por alguna razón, basándome en el ejemplo del enlace, creo que el formato podría no encajar. Aunque intentaré esto gracias. - VISQL
Hecho. Solo necesitas hacer coincidir las uniones. - tisho
0
Hay algunas respuestas sobre SO relacionadas con datos dinámicamente dinámicos: esta es una que proporcioné, y es útil saberla.
SQL Server 2008 dinámico pivote basado en valor ordinal
Al usar el operador XML PATH, también obtiene nombres de columna decentes en su conjunto de resultados.
contestado el 23 de mayo de 17 a las 11:05
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas sql-server-2008 tsql loops while-loop case or haz tu propia pregunta.
Guau. Nunca he oído hablar de SQL dinámico. Veré que puedo leer sobre esto. Mi habilidad actual no está en ese nivel. Sin embargo, parece una solución realmente compacta. Gracias. - VISQL
El código anterior no es la única forma de hacer esto: @Tisho propuso el método PIVOT, que también puede crear columnas a partir de datos de fila. Pero incluso eso no funciona en un número arbitrario de columnas o para valores arbitrarios. Entonces, para que eso funcione, aún necesita recurrir a SQL dinámico para generar el PIVOT. Básicamente, a SQL simplemente no le gusta (por una buena razón, en general) devolver datos sin una forma predefinida (número/tipo de columnas, etc.), y generalmente necesita recurrir a SQL dinámico para que lo haga. . - Domingo P