How work with subquery in a View? - sql

I need create a View for this Query, allowing change m.arq_data and m2.arq_data values when a select uses this View, like:
select * FROM the_view WHERE m.arq_data = X AND m2.arq_data = Y
Here is my current query:
SELECT distinct(p.num_processo),p.num_proc_jud,a.assunto,su.subassunto,ma.Materia,u.Unidade ,M.COD_UNIDADE as cod_serv ,u.Unidade as servidor ,' ' as serv_ativo,
' ' as data_vinc ,' ' as V_ativo, M.motivo,M.data_movimentacao as data_mov_distr ,
(select max(m2.arq_data) from movimentacao m2 where m2.arq_data
BETWEEN '2011-08-01 00:00:00'AND '2011-08-31 23:00:00' and m2.num_processo =
p.num_processo) as Data_Arq_Desarq , status = 'A'
--pra view
, M.arq_data
FROM processo p
INNER JOIN assunto a ON a.cod_assunto = p.cod_assunto
INNER JOIN subassunto su ON su.cod_subassunto = p.cod_subassunto
LEFT JOIN materia ma ON ma.cod_materia = p.cod_materia
inner JOIN movimentacao M on M.num_processo = p.num_processo
INNER JOIN Unidade u ON u.cod_unidade = M.COD_UNIDADE
where
not exists(select * from anexos a where a.num_proc_anexo = p.num_processo and a.ativo = 1)
and not exists(select * from movimentacao m1 where m1.num_movimentacao= M.num_movimentacao and m1.motivo = 10 and m1.arquivado = 0)
and ( not exists (select * from distrib_vincjud d2 where d2.num_processo = p.num_processo)
or p.num_processo in (select d3.num_processo from distrib_vincjud d3
where d3.num_processo = p.num_processo
and d3.cod_servidor not in(select cod_servidor from servidor)
and d3.id_vinc in (select max(d4.id_vinc) from distrib_vincjud d4
where d4.num_processo = d3.num_processo and d4.data_vinc <= M.arq_data )))
and M.COD_UNIDADE in (select M.COD_UNIDADE from movimentacao m2 where
(m2.cod_ORIGEM_MOV = '26000181' or m2.cod_ORIGEM_MOV = '2600000X')and m2.num_processo = p.num_processo)
and p.tipo = 'J'
and M.arq_data >= '2011-08-01 00:00:00'AND M.arq_data <='2011-08-31 23:00:00'

View cannot take parameters. Implement it as table-valued udf instead (or stored procedure).

If you are saying you want to define your view to work with changing dates for conditions like m2.arq_data BETWEEN '2011-08-01 00:00:00'AND '2011-08-31 23:00:00' then it depends what your requirements are.
For instance if this date range will always be between today and 31 days from now then you could change this line to be something like this:
m2.arq_data BETWEEN GetDate() AND DATEADD (dd, 31, GetDate())
If the date range is not something fairly simple that can be defined generically using SQL then you might want to consider using a stored proc or a udf and passing it the date params.

Related

Qlik Sense : SQL With Statement

I'm using Qlik Sense Desktop in order to create reportings.
However, i want to load datas using this request :
WITH ventes AS (SELECT Reservations.re_numero AS IDSession, InscriptionsLignes.il_montantLigneHT AS VenteSession, Reservations.re_nom AS NomSession, Tiers.ti_nom AS NomClient, CASE WHEN Tiers_2.ti_nom + ' ' + Tiers_2.ti_prenom IS NULL THEN 'Non affecté' ELSE Tiers_2.ti_nom + ' ' + Tiers_2.ti_prenom END AS NomCommercial
FROM Reservations INNER JOIN
InscriptionsEntetes ON Reservations.re_numero = InscriptionsEntetes.in_reservation INNER JOIN
InscriptionsLignes ON InscriptionsEntetes.in_numero = InscriptionsLignes.il_inscription INNER JOIN
InscriptionsTiers ON InscriptionsEntetes.in_numero = InscriptionsTiers.it_inscription AND InscriptionsLignes.il_inscription = InscriptionsTiers.it_inscription INNER JOIN
Tiers ON InscriptionsTiers.it_tiers = Tiers.ti_identifiant LEFT OUTER JOIN
Tiers AS Tiers_2 ON InscriptionsEntetes.in_idTiersConseiller = Tiers_2.ti_identifiant
WHERE (InscriptionsTiers.it_typeRattachement = '01') AND (Reservations.re_etat <> 3) AND (Reservations.re_annulation = 0) AND (InscriptionsEntetes.in_Etat <> '4')), couts AS
(SELECT Reservations_1.re_numero AS IDSession, ReservationsProduits.rp_montantPrevu AS Couts
FROM Reservations AS Reservations_1 INNER JOIN
ReservationsProduits ON Reservations_1.re_numero = ReservationsProduits.rp_numeroReservation
WHERE (Reservations_1.re_etat <> 3) AND (Reservations_1.re_annulation = 0)), tot_couts AS
(SELECT IDSession, SUM(Couts) AS couts_total
FROM couts AS couts_1
GROUP BY IDSession), tot_ventes AS
(SELECT IDSession, SUM(VenteSession) AS ventes_total
FROM ventes AS ventes_1
GROUP BY IDSession)
SELECT tvn.IDSession, tvn.ventes_total, tct.couts_total, ventes_2.NomSession, ventes_2.NomClient, ventes_2.VenteSession, ventes_2.VenteSession - tct.couts_total / (tvn.ventes_total / ventes_2.VenteSession) AS marge
FROM tot_ventes AS tvn INNER JOIN
tot_couts AS tct ON tvn.IDSession = tct.IDSession INNER JOIN
ventes AS ventes_2 ON tvn.IDSession = ventes_2.IDSession
WHERE (ventes_2.VenteSession <> 0)
ORDER BY tvn.IDSession
As you can see, I'm using the SQL With Statement but it doesn't work on Qlik, "With" is a unknown statement they said
Anyone can help me ?
Some sql commands are just recongnize in Qlik if you use the SQL statement before, e.g.:
TableName:
LOAD *;
SQL ;
TableName:
LOAD *;
SQL
WITH ventes AS (
SELECT Reservations.re_numero AS IDSession
, InscriptionsLignes.il_montantLigneHT AS VenteSession
, Reservations.re_nom AS NomSession
, Tiers.ti_nom AS NomClient
, CASE
WHEN Tiers_2.ti_nom + ' ' + Tiers_2.ti_prenom IS NULL
THEN 'Non affecté'
ELSE Tiers_2.ti_nom + ' ' + Tiers_2.ti_prenom
END AS NomCommercial
FROM Reservations
INNER JOIN InscriptionsEntetes
ON Reservations.re_numero = InscriptionsEntetes.in_reservation
INNER JOIN InscriptionsLignes
ON InscriptionsEntetes.in_numero = InscriptionsLignes.il_inscription
INNER JOIN InscriptionsTiers
ON InscriptionsEntetes.in_numero = InscriptionsTiers.it_inscription
AND InscriptionsLignes.il_inscription = InscriptionsTiers.it_inscription
INNER JOIN Tiers
ON InscriptionsTiers.it_tiers = Tiers.ti_identifiant
LEFT OUTER JOIN Tiers AS Tiers_2
ON InscriptionsEntetes.in_idTiersConseiller = Tiers_2.ti_identifiant
WHERE (InscriptionsTiers.it_typeRattachement = '01')
AND (Reservations.re_etat 3)
AND (Reservations.re_annulation = 0)
AND (InscriptionsEntetes.in_Etat '4'))
, couts AS
(SELECT Reservations_1.re_numero AS IDSession
, ReservationsProduits.rp_montantPrevu AS Couts
FROM Reservations AS Reservations_1
INNER JOIN ReservationsProduits
ON Reservations_1.re_numero = ReservationsProduits.rp_numeroReservation
WHERE (Reservations_1.re_etat 3)
AND (Reservations_1.re_annulation = 0)), tot_couts AS
(SELECT IDSession, SUM(Couts) AS couts_total
FROM couts AS couts_1
GROUP BY IDSession), tot_ventes AS
(SELECT IDSession, SUM(VenteSession) AS ventes_total
FROM ventes AS ventes_1
GROUP BY IDSession)
SELECT tvn.IDSession
, tvn.ventes_total
, tct.couts_total
, ventes_2.NomSession
, ventes_2.NomClient
, ventes_2.VenteSession
, ventes_2.VenteSession - tct.couts_total / (tvn.ventes_total / ventes_2.VenteSession) AS marge
FROM tot_ventes AS tvn
INNER JOIN tot_couts AS tct
ON tvn.IDSession = tct.IDSession
INNER JOIN ventes AS ventes_2
ON tvn.IDSession = ventes_2.IDSession
WHERE (ventes_2.VenteSession 0)
ORDER BY tvn.IDSession;
You can encapsulate your query in a parent one:
TableName:
Load *;
SQL
select *
from (
--put your WITH query here
) as temp;
Depending on your RDBMS you might not need this final alias ("as temp").

SQL Random Item for each USER

I have been searching and cannot find the right way to do this. In my query below, What I need is one random C.CREDENTIALING_K for each U.USER_K. I know the newid() will be needed somewhere, I just cannot find the proper place to put it.
select
U.USER_K,
U.FULLNAME as 'Chg_By',
CONVERT(DATE,AL.AUDITDATETIME) as 'Verif_Date',
P.ID,
P.LONGNAME,
CONVERT(DATE,P.DATEOFBIRTH) as 'DOB',
C.entity_k,
R.DESCRIPTION as 'CVI_TYPE',
C.CREDENTIALING_K,
CG.GROUPDESCRIPTION,
C.APPLICATION_RECEIVED,
R1.DESCRIPTION as 'Cur_STATUS',
CONVERT(DATE,C.USERDEF_D3) as 'MSO_DUE_DT'
from
VisualCACTUS.AUDITLOG AL
JOIN VisualCACTUS.USERS U
on U.user_k = AL.USER_K
join VisualCACTUS.CREDENTIALING C
JOIN VisualCACTUS.PROVIDERS P
on P.provider_k = C.PROVIDER_K
JOIN visualcactus.CREDENTIALINGGROUP CG
on CG.CREDENTIALINGGROUP_K = C.CREDENTIALINGGROUP_K
JOIN VisualCACTUS.REFTABLE R
on R.reftable_k = CG.TYPE_RTK
JOIN VisualCACTUS.REFTABLE R1
ON R1.REFTABLE_K = C.CREDENTIALINGSTATUS_RTK
--JOIN VisualCACTUS.CREDENTIALINGASSIGNMENTS CA
--on CA.credentialing_k = CA.credentialing_k
on C.CREDENTIALING_K = AL.FILE_PRIMARYKEY
where
AUDITLOG_K in (select AUDITLOG_K from VisualCACTUS.AUDITLOG_RECORDLEVEL where TABLE_NAME = 'CREDENTIALING '
and
AUDITLOG_RECORDLEVEL_K in (SELECT AUDITLOG_RECORDLEVEL_K from VisualCACTUS.AUDITLOG_FIELDLEVEL where NEWVALUE_SHORT = 'D2680X38F3'))
and
C.USERDEF_L1 = 0
and
CG.TYPE_RTK NOT IN ('D2870MPPSO','D2LC0YR0AR','D2DD1EIY5X')
and
CG.TYPE_RTK NOT LIKE ('SSP%')
and
C.credentialing_k not in (select credentialing_k from VisualCACTUS.CREDENTIALINGASSIGNMENTS where EA_K in (select ea_k from visualcactus.entityassignments where entity_k in ('HCA0000039',
'HCA0000040',
'HCA0000041',
'HCA0000043',
'HCA0000096',
'HCA0000095',
'HCA0000337',
'HCA0000903',
'HCA0000904',
'HCA0000905',
'HCA0000906',
'HCA0000080')))
and
CONVERT(DATE, AUDITDATETIME) = DATEADD(day, -1, convert(date, GETDATE()))
order by 'Chg_By'
Make a correlated subquery to return random CREDENTIALING_K
CREDENTIALING_K=(select top 1 C1.CREDENTIALING_K
from VisualCACTUS.CREDENTIALING c1
Where P.provider_k = C1.PROVIDER_K
order by newid())
Note : If needed add the filter that you have used for VisualCACTUS.CREDENTIALING table inside subquery too

SQL Server 2012 : Multiple Queries in One Stored Procedure

How do I create Stored Procedure on these queries and he output should show which check the anomaly was captured from, along with all the relevant data.
SELECT cm.Cust_id, cm.cust_ref_id4, cm.cust_ref_id3, cm.plan_group, cm.Company_name, cm.Cust_firstname, cm.Cust_lastname
COALESCE(c.pkCustomerID, c2.fkCustomerID, c3.pkCustomerID, c4.pkCustomerID) AS pkCustomerID, c3.CompanyName FROM PRODUCTIONSQL.[SigmaPaTri].[dbo].[CUSTOMER_MASTER] cm
LEFT JOIN PHOENIX.CORE.dbo.Customers AS c ON cust_ref_id4 = c.pkCustomerID AND cm.cust_ref_id3 = c.pkCustomerID AND cm.cust_ref_id3 >= 1000000 AND cm.Cust_firstname + ' ' + cm.Cust_lastname = c.CompanyName
LEFT JOIN PHOENIX.CORE.dbo.Contracts AS c2 ON cm.cust_ref_id3 = c2.ConfirmationNumber
WHERE cm.cust_status IN ('A','P','R','G') AND COALESCE(c.pkCustomerID, c2.fkCustomerID) IS NULL ORDER BY cust_ref_id4;
and
SELECT [pkCustomerID],b.[pkContractID],[pkCustomerTypeID],[CustomerType],b.[ContractType] AS Contractype1,c.[ContractType]
AS Contractype2 FROM [CORE].[dbo].[Customers] a
JOIN [CORE].[dbo].[CustomerTypes] ON [pkCustomerTypeID] = [fkCustomerTypeID]
LEFT JOIN (SELECT [pkContractID],[ContractType],[fkCustomerID] FROM [CORE].[dbo].[Contracts]
JOIN [CORE].[dbo].[ContractTypes] ON [fkContractTypeID] = [pkContractTypeID] WHERE [ContractType] NOT LIKE 'Holdover%')b ON a.pkCustomerID=b.fkCustomerID
LEFT JOIN (SELECT [pkContractID],[fkCustomerID],[ContractType] FROM [CORE].[dbo].[Contracts]
JOIN [CORE].[dbo].[ContractTypes] ON [fkContractTypeID] = [pkContractTypeID] WHERE ContractType LIKE 'Holdover%')c ON b.fkCustomerID=c.fkCustomerID WHERE [CustomerType] IN ('Customer','Former Customer') AND (b.ContractType IS NULL OR c.ContractType IS NULL)
You question is lacking a very important piece of information, the explanation of what you are trying to do. I took a shot in the dark here as a guess to what you might be looking for. BTW, I ran this through a formatter so it was legible.
SELECT 'Found in query1'
,cm.Cust_id
,cm.cust_ref_id4
,cm.cust_ref_id3
,cm.plan_group
,cm.Company_name
,cm.Cust_firstname
,cm.Cust_lastname
,COALESCE(c.pkCustomerID, c2.fkCustomerID, c3.pkCustomerID, c4.pkCustomerID) AS pkCustomerID
,c3.CompanyName
FROM PRODUCTIONSQL.[SigmaPaTri].[dbo].[CUSTOMER_MASTER] cm
LEFT JOIN PHOENIX.CORE.dbo.Customers AS c ON cust_ref_id4 = c.pkCustomerID
AND cm.cust_ref_id3 = c.pkCustomerID
AND cm.cust_ref_id3 >= 1000000
AND cm.Cust_firstname + ' ' + cm.Cust_lastname = c.CompanyName
LEFT JOIN PHOENIX.CORE.dbo.Contracts AS c2 ON cm.cust_ref_id3 = c2.ConfirmationNumber
WHERE cm.cust_status IN (
'A'
,'P'
,'R'
,'G'
)
AND COALESCE(c.pkCustomerID, c2.fkCustomerID) IS NULL
SELECT 'Found in query 2'
,[pkCustomerID]
,b.[pkContractID]
,[pkCustomerTypeID]
,[CustomerType]
,b.[ContractType] AS Contractype1
,c.[ContractType] AS Contractype2
FROM [CORE].[dbo].[Customers] a
INNER JOIN [CORE].[dbo].[CustomerTypes] ON [pkCustomerTypeID] = [fkCustomerTypeID]
LEFT JOIN (
SELECT [pkContractID]
,[ContractType]
,[fkCustomerID]
FROM [CORE].[dbo].[Contracts]
INNER JOIN [CORE].[dbo].[ContractTypes] ON [fkContractTypeID] = [pkContractTypeID]
WHERE [ContractType] NOT LIKE 'Holdover%'
) b ON a.pkCustomerID = b.fkCustomerID
LEFT JOIN (
SELECT [pkContractID]
,[fkCustomerID]
,[ContractType]
FROM [CORE].[dbo].[Contracts]
INNER JOIN [CORE].[dbo].[ContractTypes] ON [fkContractTypeID] = [pkContractTypeID]
WHERE ContractType LIKE 'Holdover%'
) c ON b.fkCustomerID = c.fkCustomerID
WHERE [CustomerType] IN (
'Customer'
,'Former Customer'
)
AND (
b.ContractType IS NULL
OR c.ContractType IS NULL
)

Slow TSQL query with nested selects

I have written a query, but appears to run quite slowly in our live environment.
The query contains nested select statements which I believe to slow down execution.
Does anyone have any tips of how I could re-write the query to improve the execution speed.
DECLARE #StartDate DATETIME
DECLARE #EndDate DATETIME
SET #StartDate = '20140101'
SET #EndDate = '20140101'
SELECT a.applicationid,
a.ourreference,
(SELECT MAX(e.CreateDateTime) FROM tblEmail AS e WHERE( e.ApplicationID = a.ApplicationID) AND (ISNULL(e.StandardEmailID,0) <> 3)) AS 'LastEmail',
(SELECT MAX(l.CreateDateTime) FROM tblLetter AS l WHERE l.ApplicationID = a.ApplicationID AND l.ExternalDocumentTypeID IS NULL) AS 'LastInternalLetter',
(SELECT MAX(l.CreateDateTime) FROM tblLetter AS l WHERE l.ApplicationID = a.ApplicationID AND l.ExternalDocumentTypeID IS NOT NULL) AS 'LastExternalLetter'
INTO #Temp
FROM tblapplication AS a
WHERE (a.LogDate BETWEEN #StartDate AND #EndDate + '23:59:59')
AND (a.BusinessSourceID NOT IN (11, 16))
AND (a.ApplicationStatusID = 100)
SELECT *
FROM #Temp AS tem
WHERE ((LastEmail < LastExternalLetter) AND (LastInternalLetter < LastExternalLetter))
Cheers everyone
edit- Sorry I should say what the query is for. I am trying to see if our customers have sent us a letter and we haven't responded to them with a letter/email
select *
from
(
Select a.applicationId, a.ourreference,
max(e.CreateDateTime) LastEmail,
max(li.CreateDateTime) LastInternalLetter,
max(le.CreateDateTime) LastExternalLetter
from tblApplication a
left outer join tblEmail e on e.ApplicationID = a.ApplicationID
left outer join tblLetter li on li.ApplicationId = a.ApplicationId
left outer join tblLetter le on le.ApplicationId = a.ApplicationId
WHERE (a.LogDate BETWEEN #StartDate AND #EndDate + '23:59:59')
AND (a.BusinessSourceID NOT IN (11, 16))
AND (a.ApplicationStatusID = 100)
and (e.StandardEmailID <> 3 or e.StandardEmailId is null)
group by a.ApplicationId, a.OurReference
)x
WHERE ((LastEmail < LastExternalLetter) AND (LastInternalLetter < LastExternalLetter))
This gets rid of the temporary table. Remember, with SQL wherever you have a Table you can substitute a query (in Selects anyway). This should make it a bit more efficient, but you want to look at the Query Plans and see what's holding it up.
Cheers -

SQL Show dates without transactions as value = 0

I'm doing a weight reporting and I have a problem. I use this query to know the enters of weight in our warehouse, but when there are no transactions in a date this date doesn't appears in the results.
SELECT erp.MKPF.BUDAT AS Data,
Sum( erp.MSEG.MENGE * erp.MARM.BRGEW ) as pes
From erp.MKPF
INNER Join erp.MSEG on erp.MKPF.MANDT = erp.MSEG.MANDT and erp.MKPF.MBLNR = erp.MSEG.MBLNR
INNER Join erp.MARM on erp.MSEG.MANDT = erp.MARM.MANDT and erp.MSEG.MATNR = erp.MARM.MATNR And erp.MSEG.MEINS = erp.MARM.MEINH
INNER JOIN erp.MARA on erp.MSEG.MANDT = erp.MARA.MANDT and erp.MSEG.MATNR = erp.MARA.MATNR
WHERE erp.MKPF.MANDT = '100'
and erp.MKPF.BUDAT >= '20120720'
and erp.MKPF.BUDAT <= CONVERT(VARCHAR(8), GETDATE(), 112) -1
and erp.MSEG.LGORT in ('1001','1069')
and erp.MSEG.BWART In ('101','102','311','312')
and erp.MSEG.WERKS = '1001'
and erp.MARA.MTART in ('Z001','Z010','Z002','Z02E')
GROUP BY erp.MKPF.BUDAT*
Now the results are like this:
Data PES
20120720 9999999.9999
20120721 9999999.8888
20120723 9999999.7777
And i need this
Data PES
20120720 9999999.9999
20120721 9999999.8888
20120722 0
20120723 999999.7777
Can somebody help me?
Use a table or a view to generate the date range of interest and let this drive the query. Then you outer join your results to this view. This can be done dynamically in the query. For example, in Oracle, you can use "connect by" to generate a series:
create table my_summary(the_day date, pes number);
insert into my_summary values(to_date('20120720', 'yyyymmdd'), 9999999.9999);
insert into my_summary values(to_date('20120721', 'yyyymmdd'), 9999999.8888);
insert into my_summary values(to_date('20120723', 'yyyymmdd'), 9999999.7777);
SELECT d.the_day, NVL(s.pes, 0) AS pes
FROM ( SELECT to_date('20120720', 'yyyymmdd') + level -1 AS the_day
FROM dual CONNECT BY level <= 4) d
LEFT OUTER JOIN my_summary s ON (d.the_day = s.the_day)
ORDER BY 1
THE_DAY PES
--------- ---
20-JUL-12 9999999.9999
21-JUL-12 9999999.8888
22-JUL-12 0
23-JUL-12 9999999.7777
Other rdbms have other methods to generate a series. This will require you to know the start date you want, and the number of records (in the example above 20120720 and 4).
Thanks to all, finally I did this and it works
SELECT
c.BUDAT AS DATA,
CASE When SAP.pes Is Null then '0'
ELSE SAP.pes
END
From
erp.YSD_CALENDAR as c LEFT JOIN
(SELECT
erp.MKPF.BUDAT,
Sum(
erp.MSEG.MENGE
* erp.MARM.BRGEW ) as pes
FROM
erp.MKPF
INNER Join erp.MSEG on erp.MKPF.MANDT = erp.MSEG.MANDT and erp.MKPF.MBLNR = erp.MSEG.MBLNR
INNER Join erp.MARM on erp.MSEG.MANDT = erp.MARM.MANDT and erp.MSEG.MATNR = erp.MARM.MATNR And erp.MSEG.MEINS = erp.MARM.MEINH
INNER JOIN erp.MARA on erp.MSEG.MANDT = erp.MARA.MANDT and erp.MSEG.MATNR = erp.MARA.MATNR
WHERE
erp.MKPF.MANDT = '100'
and erp.MKPF.BUDAT >= '20120720'
and erp.MSEG.LGORT in ('1001','1069')
and erp.MSEG.BWART In ('101','102','311','312')
and erp.MSEG.WERKS = '1001'
and erp.MARA.MTART in ('Z001','Z010','Z002','Z02E')
and erp.MSEG.SHKZG = 'S'
GROUP BY erp.MKPF.BUDAT
) SAP ON SAP.BUDAT = c.BUDAT
WHERE
c.BUDAT >= '20120720'
and c.BUDAT <= CONVERT(VARCHAR(8), GETDATE(), 112)
GROUP BY c.BUDAT, SAP.pes
ORDER BY c.BUDAT