Write query with subquery in CodeIgniter4 Query Builder? - sql-server

I have the following query which has an issue with Query Builder.
SELECT IIF(ISNULL(MAX(CODCLIENTE), 0) + 1 = 1,
(SELECT VALOR + 1
FROM PARAMETROS
WHERE LTRIM(RTRIM(SUBCLAVE)) = 'MINIM'
AND USUARIO = '1'),
ISNULL(MAX(CODCLIENTE), 0) + 1)
FROM CLIENTES
WHERE CODCLIENTE >= (SELECT VALOR
FROM PARAMETROS
WHERE LTRIM(RTRIM(SUBCLAVE)) = 'MINIM'
AND USUARIO = '1')
AND CODCLIENTE <= (SELECT VALOR
FROM PARAMETROS
WHERE LTRIM(RTRIM(SUBCLAVE)) = 'MAXIM'
AND USUARIO = '1');
Is there any way to do it with Query Builder? I'm currently using this method.

Related

How to optimize SQL query with subqueries

I have this query that is taking a long time to execute. I would like to know how to optimize it. What slows it down are the addition subqueries.
This is the query:
SELECT DISTINCT
dbo.Ventas.IdVenta, dbo.Ventas.CodigoVenta, dbo.Ventas.Fecha_Alta, dbo.M_Operadores.Nombre + ' ' + dbo.M_Operadores.Apellidos AS Operador, SUBSTRING(dbo.Ventas.Cliente, 0, CHARINDEX(CHAR(13), dbo.Ventas.Cliente))
AS Cliente, dbo.M_Centros.Centro,
(SELECT SUM(LineaImporte) AS Expr1
FROM dbo.Ventas_Detalle
WHERE (IdVenta = dbo.Ventas.IdVenta)) - dbo.Ventas.Redondeo AS Importe,
(SELECT ISNULL(SUM(dbo.Movimientos_Caja_Detalle.Ajuste), 0) AS Ajuste
FROM dbo.Movimientos_Caja_Detalle INNER JOIN
dbo.Movimientos_Caja ON dbo.Movimientos_Caja_Detalle.IdMovimientoCaja = dbo.Movimientos_Caja.IdMovimientoCaja
WHERE (dbo.Movimientos_Caja.IdVenta = dbo.Ventas.IdVenta)) AS Ajuste,
(SELECT ISNULL(SUM(Movimientos_Caja_Detalle_2.Importe), 0) AS Cobrado
FROM dbo.Movimientos_Caja_Detalle AS Movimientos_Caja_Detalle_2 INNER JOIN
dbo.Movimientos_Caja AS Movimientos_Caja_2 ON Movimientos_Caja_Detalle_2.IdMovimientoCaja = Movimientos_Caja_2.IdMovimientoCaja
WHERE (Movimientos_Caja_2.IdVenta = dbo.Ventas.IdVenta) OR
(Movimientos_Caja_2.CodigoSobre = dbo.Ventas.CodigoSobre) AND (Movimientos_Caja_2.IdTipoMov_Caja = 7)) AS Cobrado,
(SELECT SUM(LineaImporte) AS Expr1
FROM dbo.Ventas_Detalle AS Ventas_Detalle_1
WHERE (IdVenta = dbo.Ventas.IdVenta)) - dbo.Ventas.Redondeo -
(SELECT ISNULL(SUM(Movimientos_Caja_Detalle_1.Importe), 0) AS Cobrado
FROM dbo.Movimientos_Caja_Detalle AS Movimientos_Caja_Detalle_1 INNER JOIN
dbo.Movimientos_Caja AS Movimientos_Caja_1 ON Movimientos_Caja_Detalle_1.IdMovimientoCaja = Movimientos_Caja_1.IdMovimientoCaja
WHERE (Movimientos_Caja_1.IdVenta = dbo.Ventas.IdVenta) OR
(Movimientos_Caja_1.CodigoSobre = dbo.Ventas.CodigoSobre) AND (Movimientos_Caja_1.IdTipoMov_Caja = 7)) AS Pendiente,
(SELECT Importe AS expr1
FROM dbo.Vales
WHERE (IdVentaEmision = dbo.Ventas.IdVenta)) AS Vale, dbo.Ventas.CodigoSobre, dbo.Ventas.FechaTerminado, dbo.Ventas.IdCentro_Alta AS IdCentro, dbo.Ventas.FechaEntregado, dbo.Ventas.IdOperador,
dbo.Ventas.FacturaVenta, dbo.Ventas.FechaFactura, dbo.Ventas.EstadoFactura, dbo.Ventas.TipoFactura
FROM dbo.Ventas INNER JOIN
dbo.M_Operadores ON dbo.Ventas.IdOperador = dbo.M_Operadores.IdOperador INNER JOIN
dbo.M_Centros ON dbo.Ventas.IdCentro_Alta = dbo.M_Centros.IdCentro
This is the code after changes based on comments:
SELECT
V.IdVenta, V.CodigoVenta, V.Fecha_Alta, MO.Nombre + ' ' + MO.Apellidos AS Operador, SUBSTRING(V.Cliente, 0, CHARINDEX(CHAR(13), V.Cliente))
AS Cliente, MC.Centro,
(SELECT SUM(LineaImporte) AS Expr1
FROM Ventas_Detalle
WHERE (IdVenta = V.IdVenta)) - V.Redondeo AS Importe,
(SELECT ISNULL(SUM(Movimientos_Caja_Detalle.Ajuste), 0) AS Ajuste
FROM Movimientos_Caja_Detalle INNER JOIN
Movimientos_Caja ON Movimientos_Caja_Detalle.IdMovimientoCaja = Movimientos_Caja.IdMovimientoCaja
WHERE (Movimientos_Caja.IdVenta = V.IdVenta)) AS Ajuste,
(SELECT ISNULL(SUM(Movimientos_Caja_Detalle_2.Importe), 0) AS Cobrado
FROM Movimientos_Caja_Detalle AS Movimientos_Caja_Detalle_2 INNER JOIN
Movimientos_Caja AS Movimientos_Caja_2 ON Movimientos_Caja_Detalle_2.IdMovimientoCaja = Movimientos_Caja_2.IdMovimientoCaja
WHERE (Movimientos_Caja_2.IdVenta = V.IdVenta) OR
(Movimientos_Caja_2.CodigoSobre = V.CodigoSobre) AND (Movimientos_Caja_2.IdTipoMov_Caja = 7)) AS Cobrado,
(SELECT SUM(LineaImporte) AS Expr1
FROM Ventas_Detalle AS Ventas_Detalle_1
WHERE (IdVenta = V.IdVenta)) - V.Redondeo -
(SELECT ISNULL(SUM(Movimientos_Caja_Detalle_1.Importe), 0) AS Cobrado
FROM Movimientos_Caja_Detalle AS Movimientos_Caja_Detalle_1 INNER JOIN
Movimientos_Caja AS Movimientos_Caja_1 ON Movimientos_Caja_Detalle_1.IdMovimientoCaja = Movimientos_Caja_1.IdMovimientoCaja
WHERE (Movimientos_Caja_1.IdVenta = V.IdVenta) OR
(Movimientos_Caja_1.CodigoSobre = V.CodigoSobre) AND (Movimientos_Caja_1.IdTipoMov_Caja = 7)) AS Pendiente,
(SELECT Importe AS expr1
FROM Vales
WHERE (IdVentaEmision = V.IdVenta)) AS Vale, V.CodigoSobre, V.FechaTerminado, V.IdCentro_Alta AS IdCentro, V.FechaEntregado, V.IdOperador,
V.FacturaVenta, V.FechaFactura, V.EstadoFactura, V.TipoFactura
FROM Ventas V INNER JOIN
M_Operadores MO ON V.IdOperador = MO.IdOperador INNER JOIN
M_Centros MC ON V.IdCentro_Alta = MC.IdCentro

Temp Table VS Table variable

I have to write a table function so I prototyped the query in SQL Server and used a temp table but when I change it to a table variable the query goes from taking approx. 1 minute to more than 2 hours.
The second code is this one:
DECLARE #DETALLE TABLE
(
FECHA smalldatetime,
NO_OP NVARCHAR(100),
MONTO FLOAT,
PLAZO INT,
CLIENTE NVARCHAR(100)
)
-- CALCULO EL PLAZO POR EL MONTO, EL CUAL SERA EL NUMERADOR --
--DROP TABLE #DETALLE
INSERT INTO #DETALLE
SELECT
D.FECHA, D.NO_OP,
MONTO = (D.CAPITAL+D.INTERESES)/1000000,
PLAZO = CAST(D.FECHA_VCTO-D.FECHA AS INT),
CLIENTE = CASE
WHEN MIN_MAY = 'N' THEN 'MINORISTA'
WHEN M.ORIGEN = 'MESA LIQUIDEZ' THEN 'CLIENTE LIQUIDEZ'
WHEN M.ORIGEN IS NULL AND MIN_MAY = 'S' AND COD_SUCURSAL = '246' THEN 'EMPRESAS SALES'
ELSE 'OTRO MAYORISTA'
END
--INTO #DETALLE
FROM
BCI_RIF_ODS.dbo.Tab_Detalle_DAP AS D
INNER JOIN
BCI_RI_ODS.dbo.Cliente_Traduce AS C ON (C.CLIENTE_ID = D.CLIENTE_ID)
LEFT JOIN
BCI_RIF_ODS.dbo.TabMae_CliMesa AS M ON (D.CLIENTE_ID = M.CLIENTE_ID)
WHERE
FECHA >= '20180101' AND FECHA_VCTO > FECHA
SELECT
D1.CLIENTE, D1.FECHA,
NUMERADOR = SUM(D1.PLAZO*D1.MONTO),
MONTO = D2.MONTO,
FACTOR = SUM(D1.PLAZO*D1.MONTO)/D2.Monto
FROM
#DETALLE D1
LEFT JOIN
(SELECT
CLIENTE, FECHA,
MONTO = SUM(MONTO)
FROM
#DETALLE
GROUP BY
CLIENTE, FECHA) D2 ON (D1.CLIENTE = D2.CLIENTE AND D1.Fecha = D2.Fecha)
GROUP BY
D1.CLIENTE, D1.Fecha, D2.MONTO
You really don't need to make another copy of your data to then just perform an aggregate. You could use a cte here instead. Something like this will likely perform a lot better than copying data from one table to a variable.
with DETALLE as
(
-- CALCULO EL PLAZO POR EL MONTO, EL CUAL SERA EL NUMERADOR --
SELECT
D.FECHA, D.NO_OP,
MONTO = (D.CAPITAL+D.INTERESES)/1000000,
PLAZO = CAST(D.FECHA_VCTO-D.FECHA AS INT),
CLIENTE = CASE
WHEN MIN_MAY = 'N' THEN 'MINORISTA'
WHEN M.ORIGEN = 'MESA LIQUIDEZ' THEN 'CLIENTE LIQUIDEZ'
WHEN M.ORIGEN IS NULL AND MIN_MAY = 'S' AND COD_SUCURSAL = '246' THEN 'EMPRESAS SALES'
ELSE 'OTRO MAYORISTA'
END
FROM
BCI_RIF_ODS.dbo.Tab_Detalle_DAP AS D
INNER JOIN
BCI_RI_ODS.dbo.Cliente_Traduce AS C ON (C.CLIENTE_ID = D.CLIENTE_ID)
LEFT JOIN
BCI_RIF_ODS.dbo.TabMae_CliMesa AS M ON (D.CLIENTE_ID = M.CLIENTE_ID)
WHERE
FECHA >= '20180101' AND FECHA_VCTO > FECHA
)
SELECT
D1.CLIENTE, D1.FECHA,
NUMERADOR = SUM(D1.PLAZO*D1.MONTO),
MONTO = D2.MONTO,
FACTOR = SUM(D1.PLAZO*D1.MONTO)/D2.Monto
FROM
DETALLE D1
LEFT JOIN
(SELECT
CLIENTE, FECHA,
MONTO = SUM(MONTO)
FROM
DETALLE
GROUP BY
CLIENTE, FECHA) D2 ON (D1.CLIENTE = D2.CLIENTE AND D1.Fecha = D2.Fecha)
GROUP BY
D1.CLIENTE, D1.Fecha, D2.MONTO

MSSQL Loop - How to

I need your help on this please:
I have one table in which ID_Erreur_CallBack could be NULL, 0, 1, 2, 3, 4, 5 or 6.
If I execute:
SELECT ID_SkillGroup AS Competence
,ID_Erreur_CallBack
,count(*) AS Nombre_de_Ocurrences
,CASE ID_Erreur_CallBack
WHEN '0'
THEN 'Abandon pendant l’exécution du script (le client a raccroché)'
WHEN '1'
THEN 'Ligne occupée'
WHEN '2'
THEN 'Le client n’a pas confirmé en appuyant sur étoile'
WHEN '3'
THEN 'Le client n’a pas décroché'
WHEN '4'
THEN 'Le numéro de téléphone du client est invalide'
WHEN '5'
THEN 'Problemes de ressources lors de l’appel'
WHEN '6'
THEN 'Echec de l’appel'
ELSE 'Appel réussi'
END AS Description_Erreur
FROM dbo.TB_WCB_USER
WHERE Date_Heure_Insert BETWEEN '01/11/2015'
AND '01/12/2015'
AND TYPE = 'WCB'
GROUP BY ID_SkillGroup
,ID_Erreur_CallBack
ORDER BY ID_SkillGroup
,ID_Erreur_CallBack ASC
And I get for example:
Result
I want to make a SELECT statement where I can vary ID_Erreur_CallBack from 0 to 6 and NULL even if Nombre_de_Ocurrences is 0 (or NULL). Something like:
Result I wish
Thank you!
Instead of using a CASE You create a table with your errors description, that way is easy to mantain if you want add or update text, dont need change code.
like errors
error_id error_text
1 err1
2 err2
3 err3
....
100 'Appel réussi'
THEN use LEFT JOIN
select ID_SkillGroup as Competence,
E.error_id as ID_Erreur_CallBack,
E.error_text as Description_Erreur,
count(*) as Nombre_de_Ocurrences
FROM errors E
LEFT JOIN TB_WCB_USER W
ON E.error_id = ID_Erreur_CallBack
I see you have an ELSE on your CASE
You can do something like this
LEFT JOIN TB_WCB_USER W
ON E.error_id = CASE ID_Erreur_CallBack
WHEN > 99 then 100 -- 'Appel réussi'
ELSE ID_Erreur_CallBack
END
Thank for the answer Juan Carlos.
I finally used CROSS JOIN
/*Creation de table temporaire et remplisage avec NULL*/
WITH T1 AS (
SELECT n = 0
UNION ALL
SELECT n + 1 FROM T1 WHERE n < 6
)
SELECT n INTO #Temp_Cesar FROM T1
INSERT INTO #Temp_Cesar (n) VALUES (NULL)
SELECT t1.ID_SkillGroup as Competence,t2.n as ID_Erreur_CallBack
INTO #Temp_Cesar1
FROM dbo.TB_SKILLGROUP t1
CROSS JOIN #Temp_Cesar t2
ORDER BY t1.ID_SkillGroup
ALTER TABLE #Temp_Cesar1 ADD Nombre_de_Ocurrences INT NULL, Description_Erreur VARCHAR(30) NULL;
select Competence,isnull(ID_Erreur_CallBack,99) as ID_Erreur_CallBack,isnull(Nombre_de_Ocurrences,0) as Nombre_de_Ocurrences,
Case ID_Erreur_CallBack
WHEN '0' THEN 'Abandon pendant l’exécution du script (le client a raccroché)'
WHEN '1' THEN 'Ligne occupée'
WHEN '2' THEN 'Le client n’a pas confirmé en appuyant sur étoile'
WHEN '3' THEN 'Le client n’a pas décroché'
WHEN '4' THEN 'Le numéro de téléphone du client est invalide'
WHEN '5' THEN 'Problemes de ressources lors de l’appel'
WHEN '6' THEN 'Echec de l’appel'
ELSE 'Appel réussi'
END AS Description_Erreur
into #Temp_Cesar11 from #Temp_Cesar1

Using boolean subqueries in SELECT

SELECT A.ID AS Asta
,B.GPS.Lat AS Lng
,B.GPS.Long AS Lat
,B.Tipo AS Tipo
,B.Via AS Via
,A.Stato AS Stato
,(
SELECT COUNT(*)
FROM SIBA_Vendite
WHERE Lotto = B.Lotto
AND Data > GETDATE()
) AS Attiva
,(
SELECT TOP (1) Esito
FROM SIBA_Vendite
WHERE Lotto = B.Lotto
ORDER BY Data
) = (
SELECT ID
FROM SIBA_Esiti
WHERE NAME = 'DESERTA'
) AS Deserta
FROM SIBA_Beni B
INNER JOIN SIBA_Aste A ON B.Asta = A.ID
is returning
Messaggio 102, livello 15, stato 1, riga 1
Incorrect syntax near '='.
Messaggio 156, livello 15, stato 1, riga 1
Incorrect syntax near the keyword 'AS'.
The wrong piece is the = between two subqueries. I'm trying to get a boolean result of the = as "Deserta" field
SQL server doesn't have a boolean datatype, so you have no choice but to use a case or an iif expression to handle this case.
e.g.
Deserta =case when (SELECT TOP (1) Esito
FROM SIBA_Vendite
WHERE Lotto = B.Lotto
ORDER BY Data) = (
SELECT ID
FROM SIBA_Esiti
WHERE NAME = 'DESERTA'
) then 1 else 0 end

Dynamic Temporal SQL Server 2005 Table by CASE

I need to define temporal table depending of value of parameter, I put this code:
CASE #estadoFacturacion
WHEN 1 THEN SELECT * INTO #EstadoFacturacion FROM f_lineas_proceso_pendiente(#custCod) --PROCESOS QUE NO TIENEN NINGUNA FACTURA ASOCIADA
WHEN 2 THEN SELECT * INTO #EstadoFacturacion FROM f_lineas_proceso_FactParcial(#custCod) --PROCESOS CON, AL MENOS, 1 TRAMO FACTURADO
WHEN 3 THEN SELECT * INTO #EstadoFacturacion FROM f_lineas_proceso_AbonoParcial(#custCod) --PROCESOS CON, AL MENOS, 1 TRAMO ABONADO
WHEN 4 THEN SELECT * INTO #EstadoFacturacion FROM f_lineas_proceso_Facturada(#custCod) --PROCESOS CON TODOS LOS TRAMOS FACTURADOS
WHEN 5 THEN SELECT * INTO #EstadoFacturacion FROM f_lineas_proceso_Abonada(#custCod) --PROCESOS CON TODOS LOS TRAMOS ABONADO
ELSE SELECT CONVERT(VARCHAR, LP.fk_proyecto_id) + '-' + CONVERT(VARCHAR,LP.linea) IdProyLinea INTO #EstadoFacturacion FROM lineas_proceso LP --TODOS LOS PROCESOS
But it doesn't works...
¿How can I do this?
Thanks.
SQL server does not have a CASE statement, only a CASE expression. So use an IF ELSE IF ladder instead:
IF #estadoFacturacion = 1
BEGIN
SELECT *
INTO #EstadoFacturacion
FROM f_lineas_proceso_pendiente(#custCod)
END
ELSE IF #estadoFacturacion = 2
BEGIN
SELECT *
INTO #EstadoFacturacion
FROM f_lineas_proceso_FactParcial(#custCod)
END
...
ELSE
BEGIN
SELECT CONVERT(VARCHAR, LP.fk_proyecto_id) + '-' + CONVERT(VARCHAR,LP.linea) Id
INTO #EstadoFacturacion
FROM lineas_proceso LP
END

Resources