Category Archives: Windows Server

Hacer Ciclos o iteraciones en SQL Server / How to make cycles or iterate in SQL Server


Iteración-2

Algunas veces necesitamos en un store procedure recorrer un conjunto de resultados, vamos a usar tablas temporales para este ejemplo. / Sometimes we need to iterate over a resultset, let’s use some temporary tables in this example:

create table #tmpartic(codigo varchar(10), nombre varchar(50), price int)
insert into #tmpartic values('001', 'KEYBOARD / TECLADO', 70)
insert into #tmpartic values('002', 'MOUSE / RATON', 90)
insert into #tmpartic values('003', 'PEN / LAPICERO', 45)
insert into #tmpartic values('004', 'DISPLAY / MONITOR', 150)
insert into #tmpartic values('005', 'HARD DISK / DISCO DURO', 200)

create table #tmpcli(client varchar(10), City varchar(30), limit int)
insert into #tmpartic values('5551010', 'Bogota', 100)
insert into #tmpartic values('5156225', 'Bangladesh', 300)
insert into #tmpartic values('6859852', 'Pekin', 500)
insert into #tmpartic values('7851215', 'Tokio', 500)
insert into #tmpartic values('8989822', 'Sidney', 350)

create table #tmpped(client varchar(10), article varchar(10), price int)

Ahora necesitamos crear registros en la tabla tmpcli para cada cliente todos los artículos mientras no se pase de su límite. /

Now we need to create records in tmpcli table for each client every article without being over limit.

Para esto creamos 2 tablas temporales #tmpartic con cada artículo y su precio y #tmpcli con cada cliente y su límite. El ciclo principal es sobre la tabla temporal de clientes entonces obtenemos su límite y mientras tenga límite disponible agregamos un registro en la tabla #tmpped, por cada registro agregado vamos disminuyendo el precio del artículo para que no se vaya a pasar. El ciclo while se controla mediante la columna kctrl que empieza en null y tras cada iteración cambia a 1 así ya no se procesa más. Para los artículos se debe volver a actualizar en null cuando se cambia de cliente para garantizar que se procesan de nuevo todos los artículos para cada cliente. /

For this we create 2 temporary tables #tmpartic with each article and price y #tmpcli for each client and limit. Main cycle runs on clients temporary table, we read his limit and while limit is available we add a new record in #tmpped, for each record added we subtract the price of the article preventing to add more than expected. The cycle is controled with the column kctrl that starts in null and after every iteration it changes to 1 that way is no longer used. For the articles this column must be updated to null when client is changed to warranty all the articles are processed for each client.

DECLARE @nLIMIT int, @nRECNUM int, @cCLI varchar(10);
DECLARE @nRECNP int, @cART varchar(10), @nPRIC int;
SELECT null kctrl, codigo, price, ROW_NUMBER() OVER(ORDER BY codigo) as recnum into #selpro FROM #tmpartic;
SELECT null kctrl, client, limit, ROW_NUMBER() OVER(ORDER BY limit) as recnum into #selcli FROM #tmpcli;
WHILE (SELECT count(*) FROM #selcli WHERE isnull(kctrl, 0) = 0) > 0
BEGIN
  SET @nRECNUM=(SELECT MIN(recnum) FROM #selcli WHERE ISNULL(kctrl, 0) = 0)
  SELECT @nLIMIT=limit, @cCLI=client FROM #selcli WHERE recnum=@nRECNUM
  UPDATE #selpro SET kctrl=null
  WHILE (SELECT count(*) FROM #selpro WHERE isnull(kctrl, 0) = 0) > 0
    BEGIN
      SET @nRECNP=(SELECT MIN(recnum) FROM #selpro WHERE ISNULL(kctrl, 0) = 0)
      SELECT @cART=codigo, @nPRIC=price FROM #selpro WHERE recnum=@nRECNP
      IF @nLIMIT>=@nPRIC
        BEGIN
          INSERT INTO #tmpped(client, article, price) VALUES(@cCLI, @cART,@nPRIC)
          SET @nLIMIT=@nLIMIT-@nPRIC
        END
      ELSE BREAK
      UPDATE #selpro SET kctrl=1 WHERE recnum=@nRECNP
  END
  UPDATE #selcli SET kctrl=1 WHERE recnum=@nRECNUM
END

Ahora vamos a validar / let’s now validate:
SELECT * from #selcli

clientes

SELECT * from #selpro
articles

SELECT * from #tmpped
peds

Verificación de resultados / Verification of results

Client $Limit $Total Peds ok?
5551010 100 70 Yes
5156225 300 205 Yes
8989822 350 205 Yes
6859852 500 355 Yes
7851215 500 355 Yes

Ahora usted podría cambiar los límites en los clientes y reiniciar el proceso para validar contra diferentes valores /

Now you can change the limits in client and restart the process to verify against different values.

Para borrar todas las tablas / to delete all the tables:

DROP TABLE #tmpartic
DROP TABLE #tmpcli
DROP TABLE #tmpped
DROP TABLE #selpro
DROP TABLE #selcli

Preguntas? / Questions?

Seleccionar registros de una tabla y todos sus registros relacionados. / Select records from a table and all related records.


Este es el comportamiento por defecto de un select sobre múltiples tablas relacionadas, nos devuelve un resultado completo incluyendo los registros de la tabla principal más todos los relacionados / This is the default behavior when performing queries against multiple related tables.

create table #tmpartic(codigo varchar(10), nombre varchar(50))
insert into #tmpartic values('001', 'KEYBOARD / TECLADO')
insert into #tmpartic values('002', 'MOUSE / RATON')
insert into #tmpartic values('003', 'PEN / LAPICERO')
insert into #tmpartic values('004', 'DISPLAY / MONITOR')
insert into #tmpartic values('005', 'HARD DISK / DISCO DURO')

create table #tmpbars(article varchar(10), codbar varchar(20))
insert into #tmpbars values('001', '8909001212')
insert into #tmpbars values('001', '8909001213')
insert into #tmpbars values('001', '8909001214')
insert into #tmpbars values('003', '8909051223')
insert into #tmpbars values('004', '8909061245')
insert into #tmpbars values('005', '8909071241')
insert into #tmpbars values('005', '8909071242')

create table #tmpprov(article varchar(10), proveed varchar(10))
insert into #tmpprov values('001', '101010')
insert into #tmpprov values('001', '102010')
insert into #tmpprov values('001', '103010')
insert into #tmpprov values('002', '102010')
insert into #tmpprov values('003', '103010')
insert into #tmpprov values('004', '101010')
insert into #tmpprov values('004', '102010')
insert into #tmpprov values('004', '104020')
insert into #tmpprov values('005', '104030')

Ahora vamos a seleccionar con un left normal / select with a normal “left” query :

select art.codigo, art.nombre, isnull(bar.codbar,'') as codbar, isnull(pro.proveed,'') as proveed
from #tmpartic art
left join #tmpbars bar on art.codigo=bar.article
left join #tmpprov pro on art.codigo=pro.article

Esto nos retorna todos los registros repetidos artículos en barras y en proveed, se puede ver el artículo 001 que se repite 9 veces / this is returning 9 repeated records of the article 001:

todoslosregistros
Record with all related records

Otra forma de conseguir el mismo resultado:

select art.codigo, art.nombre, isnull(bar.codbar,'') as codbar, isnull(pro.proveed,'') as proveed
from #tmpartic art
outer apply (select * from #tmpbars where art.codigo=article ) bar
outer apply (select * from #tmpprov where art.codigo=article ) pro

Y finalmente, esto para motivos solo de verificación de velocidad o solo por diversión, un select que devuelve una combinación completa de todos los registros. /And finally just to check execution performance or just for fun, a query that returns a complete combination of all records:


select art.codigo, art.nombre, bar.codbar, pro.proveed
from #tmpartic art, #tmpbars bar, #tmpprov pro

exponentialrecords
Exponential

Filas a Columnas SQL Server / Rows to Cols in SQL Server


Tenemos una consulta de 4 columnas y las 2 primeras las necesitamos tal como se ven pero de las 2 siguientes la 3ra la necesitamos como columnas según el contenido que tenga y la cuarta como los datos que van en dicha nueva columna. De tal forma que si en la 3ra columna hay 3 o 5 diferentes datos, se crearán 3 o 5 nuevas columnas. A continuación unos datos de ejemplo para entender bien el proceso. / We have 4 Cols and the first 2 we need them exactly as they are, but the next 2 this way, the third must be new colum as different value it has, the fourth is the data for the columns created by the third one. Now this is an example to understand better this process:


create table #tmpartic(codigo varchar(10), nombre varchar(50))
create table #tmpartic_idi(artic varchar(10), idioma varchar(3), traducc varchar(50))
create table #tmpidioma(codigo varchar(3), nombre varchar(50))


insert into #tmpidioma values('ENG', 'ENGLISH')
insert into #tmpidioma values('CAT', 'CATALÀ')
insert into #tmpidioma values('FRE', 'FRENCH')


insert into #tmpartic values('001', 'HELADO DE VAINILLA')
insert into #tmpartic values('002', 'HELADO DE CHOCOLATE')
insert into #tmpartic values('003', 'MALTEADA DE FRESA')
insert into #tmpartic values('004', 'TORTA DE QUESO')
insert into #tmpartic values('005', 'CREMA BATIDA')


insert into #tmpartic_idi values('001','ENG', 'VANILLA ICE CREAM')
insert into #tmpartic_idi values('001','CAT', 'GELAT DE VAINILLA')
insert into #tmpartic_idi values('001','FRE', 'GLACE À LA VANILLE')
insert into #tmpartic_idi values('002','ENG', 'CHOCOLATE ICE CREAM')
insert into #tmpartic_idi values('002','CAT', 'GELAT DE XOCOLATA')
insert into #tmpartic_idi values('002','FRE', 'GLACE AU CHOCOLAT')
insert into #tmpartic_idi values('003','ENG', 'STRAWBERRY SHAKE')
insert into #tmpartic_idi values('003','CAT', 'MALTAT DE MADUIXA')
insert into #tmpartic_idi values('003','FRE', 'FRAISE MALTE')
insert into #tmpartic_idi values('004','ENG', 'CHEESECAKE')
insert into #tmpartic_idi values('004','CAT', 'COCA DE FORMATGE')
insert into #tmpartic_idi values('004','FRE', 'GÂTEAU AU FROMAGE')
insert into #tmpartic_idi values('005','ENG', 'WHIPPED CREAM')
insert into #tmpartic_idi values('005','CAT', 'CREMA BATUDA')
insert into #tmpartic_idi values('005','FRE', 'CRÈME FOUETTÉE')

--esta es la consulta normal que nos muestra las traducciones por cada artículo un dato interesante "article" es la misma palabra para catalán, inglés y francés.
--this is the normal query to bring all the translations for each article by the way "article" is the same word in the 3 languages
select A.CODIGO, A.NOMBRE, C.NOMBRE as IDIOMA, B.TRADUCC
from #tmpartic A
join #tmpartic_idi B on A.CODIGO=B.ARTIC
join #tmpidioma C on B.IDIOMA=C.CODIGO

Esta consulta muestra todos los artículos con cada traducción en estilo filas. / This query is showing all the articles with each traduction in row style:

Resultado Normal
Normal resultset, we want to change the IDIOMA data to cols

--ahora, aquí está la magia, nosotros le decimos al sql server que le proporcionaremos los nombres de columnas en la variable @cols
--now, here is the magic, we are telling sql server that we will provide the column names in the @cols variable
--then we will query the data with the dynamic result for the columns.
declare @cols as nvarchar(4000), @query as nvarchar(4000)
select @cols=STUFF((select ',' + quotename(RTRIM(NOMBRE))
from #tmpidioma group by nombre for xml path(''),type).value('.', 'varchar(4000)'),1,1,'')
--print @cols
set @query= N'select codigo,nombre,'+@cols+ N' from (
select A.CODIGO, A.NOMBRE, C.NOMBRE as IDIOMA, B.TRADUCC
from #tmpartic A
join #tmpartic_idi B on A.CODIGO=B.ARTIC
join #tmpidioma C on B.IDIOMA=C.CODIGO
where 1=1
) P PIVOT(
max(traducc) for idioma in ('+@cols+N')
) as pivot_table '
--print @query
exec sp_executesql @query

Y este es el resultado final. / This is the final result:

Resultado Esperado
Resultset rows to cols

Todo se puede hacer en un script sql, pero también se puede crear un stored procedure. Depende de para que necesite utilizar este proceso. / You can do this in a script sql file, but also you can create a stored procedure. It depends on the requirement that you are working on.

Deshabilitar server manager windows 2012 server


Cuando se abre una sesión en Windows Server 2012 siempre le aparece una ventana de Server Manager > Dashboard y en realidad no la necesita cada vez? Se puede deshabilitar para el usuario actual y también una tarea programada que se ejecuta por cada usuario que hace login en el servidor. Ver imágenes.