Need help adding WHERE clause in pre-written SQL statement - sql-server

Preface: my SQL is rudimentary. I received a SQL query from a vendor, it selects and exports every single employee comment and other data from a few different DBs as CSV meant for import, it was written by them but they're not helping with this request. The query is pulling so much data it makes a large time consuming file for import. So I want to add to / modify the query to have a "WHERE date > whateverdate" to narrow my results to recent data. For example, I want to pull only comments entered in the past 2 days.
The column I'm looking to add the clause for is the column "A.CMS502", defined as datetime. I believe this is the only relevant column in this query. An example date in this column is "2003-10-06 17:05:21.000". I am using SQL Server 2008 if it helps. Is it possible here? Thank you.
SELECT
'ID,Acct/LnNbr,NoteCreatedDate,CollectorId,ApplytoAll,Note'
UNION ALL
SELECT
ID + ',' + ID + ',' + NoteCreatedDate + ',' + CollectorId + ',' + 'No' + ',' + Note
FROM
(SELECT
CASE WHEN SUBSTRING(A.CMS301,LEN(A.CMS301),1) = 'S'
THEN SUBSTRING(A.CMS301,1,LEN(A.CMS301) - 1)
ELSE A.CMS301
END + '-' +
CASE WHEN SUBSTRING(A.CMS301,LEN(A.CMS301),1) = 'S'
THEN 'S' ELSE 'L'
END AS [ID],
REPLACE(CONVERT(VARCHAR, A.CMS501, 10), '-', '') AS [NoteCreatedDate],
CASE WHEN U.CMS1201 IS NOT NULL
THEN U.CMS1205 + ' ' + U.CMS1204
ELSE (SELECT CMS1205 + ' ' + CMS1204 FROM sysUSER WHERE CMS1201 = 'PSUSER')
END AS CollectorId,
CAST(A.CMS512 AS NVARCHAR(MAX)) AS [Note]
FROM
ACTIVITY AS A
LEFT JOIN
sysUSER AS U ON A.CMS503 = U.CMS1201
WHERE
A.CMS504 NOT IN (411,500,511,711,804,900,901,903,907,2000,999777)
AND A.CMS504 NOT BETWEEN 1102 AND 1199) AS S

Try this, this will output last 2 days.
SELECT 'ID,Acct/LnNbr,NoteCreatedDate,CollectorId,ApplytoAll,Note'
UNION ALL
SELECT ID + ',' + ID + ',' + NoteCreatedDate + ',' + CollectorId + ',' + 'No' + ',' + Note
FROM
(
SELECT CASE WHEN SUBSTRING(A.CMS301,LEN(A.CMS301),1) = 'S' THEN SUBSTRING(A.CMS301,1,LEN(A.CMS301) - 1) ELSE A.CMS301 END
+ '-' + CASE WHEN SUBSTRING(A.CMS301,LEN(A.CMS301),1) = 'S' THEN 'S' ELSE 'L'
END AS [ID]
,REPLACE(CONVERT(varchar,A.CMS501,10),'-','') AS [NoteCreatedDate]
,CASE WHEN U.CMS1201 IS NOT NULL THEN U.CMS1205 + ' ' + U.CMS1204 ELSE
(SELECT CMS1205 + ' ' + CMS1204 FROM sysUSER WHERE CMS1201 = 'PSUSER')
END AS CollectorId
,CAST(A.CMS512 AS nvarchar(max)) AS [Note]
FROM ACTIVITY AS A
LEFT JOIN sysUSER AS U
ON A.CMS503 = U.CMS1201
WHERE A.CMS504 NOT IN (411,500,511,711,804,900,901,903,907,2000,999777)
AND A.CMS504 NOT BETWEEN 1102 AND 1199
AND A.CMS502 >= DATEADD(D, -2, GETDATE())
) AS S

Related

Order by Empty String Last on Concatenated Column

I am trying to order a table alphabetically, ascending, with nulls last but am having problems.
The code below produces the following error:
ORDER BY items must appear in the select list if SELECT DISTINCT is specified.
select distinct
'item' = othertab..item,
'stockedFor' = tab..stocked_for
+ ', ' + tab..stockedFor2
+ ', '+ tab..stockedFor3
from tab
order by case when stockedFor is null then 1 else 0 end, stockedFor
How can I return stockedFor alphabetically and nulls last?
Just wrap it in another select statement:
select stockedFor
from (
select distinct
'stockedFor' = tab..stocked_for
+ ', ' + tab..stockedFor2
+ ', '+ tab..stockedFor3
from tab
) x
order by case when stockedFor is null then 1 else 0 end, stockedFor
Since you are removing duplicates, a workaround is to use GROUP BY to remove duplicates instead of DISTINCT. The question has changed but the method still applies if putting all columns in the SELECT in the GROUP BY.
For example:
select
'item' = othertab..item,
'stockedFor' = tab..stocked_for
+ ', ' + tab..stockedFor2
+ ', '+ tab..stockedFor3
from tab
GROUP BY othertab..item,
tab..stocked_for
+ ', ' + tab..stockedFor2
+ ', '+ tab..stockedFor3
order by case when stockedFor is null then 1 else 0 end, stockedFor

FOR XML PATH : DISTINCT sort cost increased

I'd like to put together only unique values in the concatenated string. My code is currently:
SELECT PITEM2.orderid,
(SELECT ISNULL(E.FIRSTNAME + ' ' + E.LASTNAME,' ') + ', ' AS [text()]
FROM F_PURCHASEITEM PITEM1
LEFT JOIN E__EMPLOYEE E ON e.EMPLOYEEID=PITEM1.APPROVED_BY
WHERE PITEM1.ORDERID = PITEM2.ORDERID
AND PITEM1.PISTATUS =
(SELECT POSTATUSID
FROM F_POSTATUS
WHERE POSTATUSNAME = 'Invoice Received') GROUP By ISNULL(E.FIRSTNAME + ' ' + E.LASTNAME,' ') + ', '
FOR XML PATH ('') ) [EmployeeNames]
FROM F_PURCHASEITEM PITEM2
WHERE ORDERID=305089 Group By PITEM2.orderid
This gives me the output I'd expect, but the cost of the query increased and execution plan shows the Distinct sort as 46.3%.
How can I decrease the cost for this distinct?

Generate XML from SQL issue

I need to generate XML in the following format :
I haven't gone too far with the xml part of the task as I encountered following situation, you can tell that this obviously was not my intention.
How can I handle this properly considering that BBAN and IBAN need to be inside AccountNoas well as that I want it formatted according to the first picture.
The complete query along with my fair attempt of generating xml looks like this:
DECLARE #AccountType NVARCHAR(3);
DECLARE #kodBanke NVARCHAR(3);
SET #AccountType = 'T';
SET #kodBanke = ( SELECT vrednost FROM dbini WHERE IDENT = 'KOD' AND SECTION = 'PP' );
WITH Ent_Posta
AS
(
SELECT e.naziv,p.posta,e.sifra
FROM entitet AS e
INNER JOIN poste AS p ON e.sifra = p.entitet
)
SELECT (
SELECT
[dbo].[brojracuna](#kodBanke,i.partija) AS 'BBAN',
[dbo].[GENERATEIBAN](i.partija) AS 'IBAN'
FOR XML PATH('AccountNo'), ELEMENTS, ROOT('Account')
),
#accountType AS 'AccountType',
(a.ime + ' ( ' + a.roditel + ' ) ' + a.prezime) AS 'Name',
a.embg AS 'UID',
CASE status
WHEN 2 THEN 'A'
WHEN 4 THEN 'B'
WHEN 8 THEN 'U'
END AS 'Status',
c.sifra AS 'Territory',
#kodBanke as 'ID_Bank',
REPLACE(CONVERT(VARCHAR(10), i.DOTVaRANJE, 120), '.', '') + '-' + RIGHT( '0' + CONVERT(VARCHAR(2), DATEPART(hh, i.DOTVaRANJE)), 2) + '' + RIGHT('0' + CONVERT(VARCHAR(2), DATEPART(mi, i.DOTVaRANJE)), 2) + '' + RIGHT('0' + CONVERT(VARCHAR(2), DATEPART(s, i.DOTVaRANJE)),2) AS OpeningDate,
REPLACE(CONVERT(VARCHAR(10),'2006.09.28 ', 120), '.', '') + '-' + RIGHT( '0' + CONVERT(VARCHAR(2), DATEPART(hh, '2006.09.28' )), 2) + '' + RIGHT('0' + CONVERT(VARCHAR(2), DATEPART(mi, '2006.09.28 ')), 2) + '' + RIGHT('0' + CONVERT(VARCHAR(2),DATEPART(s,'2006.09.28 ')),2) AS ClosingDate
FROM adresar AS a
INNER JOIN istdden AS i
ON a.embg = i.embg
INNER JOIN Ent_Posta as c
ON a.postbroj = c.posta
FOR XML PATH ('Account'), ROOT('Accounts');
Upon removal of this part I get...
<Accounts>
<Account>
<BBAN>5710543102313248</BBAN>
<IBAN>BA39531231634039248</IBAN>
<AccountType>T</AccountType>
<Name>DARKO ( DRAGAN ) TESIC</Name>
<UID>0000005467234</UID>
<Status>A</Status>
<Territory>1</Territory>
<ID_Bank>571</ID_Bank>
<OpeningDate>20081205-000000</OpeningDate>
<ClosingDate>20060928-000000</ClosingDate>
</Account>
... but now AccountNO is missing.
Your question is not all clear, but - if I get this correctly - you are fighting with 1:1 values, but within some deeper nesting.
You can use an XPath-like expression within [] in connection with FOR XML PATH. Check this out:
SELECT 'blah' AS FirstNode
,'blub' AS [SecondNode/OneDeeper]
,'blib' AS [SecondNode/OneMore]
,'ballaballa' AS [ThirdNode]
FOR XML PATH('row'),ROOT('root');
the resutl (look especially at <SecondNode>:
<root>
<row>
<FirstNode>blah</FirstNode>
<SecondNode>
<OneDeeper>blub</OneDeeper>
<OneMore>blib</OneMore>
</SecondNode>
<ThirdNode>ballaballa</ThirdNode>
</row>
</root>
If this is not what you need, please tag with the actual RDBMS (product and version) and please read How to ask a good SQL question and How to create a MCVE
For your issue it might be enough to use AS [AccountNo/IBAN] in your query.

Error 512: Subquery returned more than 1 value

my SQL is:
SELECT DB1.IdUtente
,DB2.Gruppo
,DB1.Username
,DB1.Psw
,CASE WHEN DB1.RagioneSociale IS NOT NULL
AND DB1.RagioneSociale <> ''
THEN DB1.RagioneSociale
ELSE DB1.Cognome + ' ' + DB1.Nome
END AS Nominativo
,DB1.Indirizzo + ' - ' + DB1.Cap+ ' ' + DB1.Citta + '(' + DB1.Provincia + ')' AS IndirizzoCompleto
,DB1.Telefono + ' ' + DB1.Email AS Contatti
,(SELECT DISTINCT COUNT (*)
FROM DB3
WHERE DB3.IdAttivazione = DB1.IdUtente
) AS NumeroAccessi
,(SELECT DB4.NumTarga
FROM DB4
WHERE DB4.IdUtente = DB1.IdUtente
) AS NumeroTarghe
,DB1.DataRegistrazione
,DB1.DataScadenza
,DB1.Attivo
FROM DB1
INNER JOIN DB2
ON DB1.IdGruppo = DB2.IdGruppo
WHERE DB1.Demo = 0
ORDER BY DB1.RagioneSociale
Why i receive this error from sql server?
Error 512: Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
What am i wrong?
Sorry for bad english.
Thanks for any help
Kind Regards
M.W.
Your sub-selects should be rewritten as joins even if your code was working without issue.
If you do this and actually do some testing across your whole dataset you will see where your duplication is coming from, which is giving you more than one row and causing the error you are seeing:
SELECT DB1.IdUtente
,DB2.Gruppo
,DB1.Username
,DB1.Psw
,CASE WHEN DB1.RagioneSociale IS NOT NULL
AND DB1.RagioneSociale <> ''
THEN DB1.RagioneSociale
ELSE DB1.Cognome + ' ' + DB1.Nome
END AS Nominativo
,DB1.Indirizzo + ' - ' + DB1.Cap+ ' ' + DB1.Citta + '(' + DB1.Provincia + ')' AS IndirizzoCompleto
,DB1.Telefono + ' ' + DB1.Email AS Contatti
,DB3.NumeroAccessi
-- Somewhere in your data you will have at least two rows with different values in this field.
,DB4.NumTarga AS NumeroTarghe
,DB1.DataRegistrazione
,DB1.DataScadenza
,DB1.Attivo
FROM DB1
INNER JOIN DB2
ON DB1.IdGruppo = DB2.IdGruppo
INNER JOIN (SELECT IdAttivazione
,COUNT(*) as NumeroAccessi
FROM DB3
GROUP BY IdAttivazione
) DB3
ON DB3.IdAttivazione = DB1.IdUtente
INNER JOIN DB4
ON DB4.IdUtente = DB1.IdUtente
WHERE DB1.Demo = 0
ORDER BY DB1.RagioneSociale

Cannot set the Order By to my SQL Statement, need a workaround

I understand that I cannot have the SQL order by PaymentDate but my results come out not in Payment Date Order. Is there an easy way I can make sure the PERIOD column is in actual date order?
The SQL below works perfect its just if i add "--order by f.PaymentDate" I get 'Column "PaymentItem.PaymentDate" is invalid in the ORDER BY clause because it is not contained in either an aggregate function or the GROUP BY clause.' So i'm trying to think how to get around this
select g.SiteDescription,
case a.Surname when '' then a.Company else a.Surname + ', ' + isnull(a.Forename,'') end as Landowner,
h.PaymentTypeDesc as [RentalElection],
d.RelevantProportion,#IN_showRelevantProportion as ShowRelevantProportion,
g.SiteId,a.LandownerId,e.PaymentTypeId,e.PaymentCategoryId,
case #IN_OutputFormat
when 'Monthly' then
convert(char(3), f.PaymentDate, 0) + '-' + ltrim(Year(f.PaymentDate))
when 'Annually' then
ltrim(Year(f.PaymentDate))
else
ltrim(Year(f.PaymentDate)) + ' Qtr ' + ltrim(datepart(quarter,f.PaymentDate))
end as Period,
sum(isnull(f.ActualPayment,0)) as Total
from
[Site] g,
Landowner a,
[Site] c,
SiteAgreement d,
Payment e,
PaymentItem f,
PaymentType h
where a.LandownerId = d.LandownerId
and g.SiteId = d.SiteId
and e.SiteAgreementId = d.SiteAgreementId
and f.PaymentId = e.PaymentId
and e.PaymentTypeId = h.PaymentTypeId
and f.paymentdate between #IN_daysFrom and #IN_daysTo
and isnull(f.ActualPayment,0) != 0
group by g.SiteDescription,
case a.Surname when '' then a.Company else a.Surname + ', ' + isnull(a.Forename,'') end,
h.PaymentTypeDesc,
d.RelevantProportion,
g.SiteId,a.LandownerId,e.PaymentTypeId,e.PaymentCategoryId,
case #IN_OutputFormat
when 'Monthly' then
convert(char(3), f.PaymentDate, 0) + '-' + ltrim(Year(f.PaymentDate))
when 'Annually' then
ltrim(Year(f.PaymentDate))
else
ltrim(Year(f.PaymentDate)) + ' Qtr ' + ltrim(datepart(quarter,f.PaymentDate))
end
--order by f.PaymentDate
Order by the entire expression that uses your Payment Date column:
ORDER BY case #IN_OutputFormat
when 'Monthly' then
convert(char(3), f.PaymentDate, 0) + '-' + ltrim(Year(f.PaymentDate))
when 'Annually' then
ltrim(Year(f.PaymentDate))
else
ltrim(Year(f.PaymentDate)) + ' Qtr ' + ltrim(datepart(quarter,f.PaymentDate))
end
I got this going by just ordering at a string in format YYYY-MM. The MM needed left padded 0 of course:
CONVERT(CHAR(4), f.PaymentDate, 120) + ' ' + right('0'+ rtrim(ltrim(datepart(mm,f.PaymentDate))), 2)

Resources