I am using the following query to gather some information about each ProductId - note that a ProductId can contain several records in the dbo.Sales table:
SELECT
c.ProductId,
COUNT(*) as NumberOfRecords,
(SELECT
(ISNULL(NULLIF(c.Text, ''), 'FALSE'))) as TextFieldHasData
FROM dbo.Sales c
JOIN dbo.Sources s
ON c.ProductId = s.ProductId
AND s.SourceStatusId in (1,2)
GROUP BY c.ProductId, c.Status, s.SourceStatusId, c.Text
ORDER BY c.ProductId
I need to tweak the ISNULL part of the query, and I'm having trouble with the syntax; what I actually need to do is first check the NumberofRecordscount - if the the NumberofRecords count for a given result record is greater than 1, then the TextFieldHadData field for that record should just say 'N/A'. But, if the NumberofRecordscount for a given result record = 1, then it should check whether the c.Text field is NULL or blank. If it is NULL or Blank, the TextFieldHasData field would say 'FALSE.' If it is not NULL or blank, the TextFieldHasData field would say 'TRUE.'
Looking at your code, perhaps you are looking for something like the following (where you would be grouping up to ProductId level):
SELECT
c.ProductId
, COUNT(*) as NumberOfRecords
,
CASE
WHEN COUNT(*) > 1
THEN 'N/A'
ELSE
CASE
WHEN SUM(CASE WHEN ISNULL(c.Text, '') = '' THEN 0 ELSE 1 END) > 0
THEN 'TRUE'
ELSE 'FALSE'
END
END TextFieldHasData
FROM
dbo.Sales c
JOIN dbo.Sources s ON
c.ProductId = s.ProductId
AND s.SourceStatusId in (1, 2)
GROUP BY c.ProductId
ORDER BY c.ProductId
You can use the query:
I can not validate it as I don't have these tables, but it should work, unless you find a minor syntax error.
The idea is to use "case when ..." sql function
select v.productid,v.NumberOfRecords,
case
when v.NumberOfRecords>1 then 'N/A'
when v.NumberOfRecords=1 and isnull(v.TextFieldHasData,'') ='' then 'FALSE'
else 'TRUE' end [textfieldhasdata]
from(
SELECT
c.ProductId,
COUNT(*) as NumberOfRecords,
(SELECT
(ISNULL(NULLIF(c.Text, ''), 'FALSE'))) as TextFieldHasData
FROM dbo.Sales c
JOIN dbo.Sources s
ON c.ProductId = s.ProductId
AND s.SourceStatusId in (1,2)
GROUP BY c.ProductId, c.Status, s.SourceStatusId, c.Text) v
ORDER BY ProductId
Related
I am running a data quality check on multiple tables and columns in a database.
If the column contains at least one duplciate, it fails the test and PassFail returns 0. Likewise if it contains no duplicates, it passses the test and PassFail returns 1.
The 1s and 0s from PassFail is then fed to an average to calculate an overall data quality score.
SELECT
'[Plant.Asset]' AS TableName
,'[ASSETNUM]' AS ColumnName
,COUNT(1) AS TotalRows
,0 AS PassFail
FROM Plant.Asset a
INNER JOIN Plant.Loc AS B ON A.LOCATION = B.LOCATION
GROUP BY
A.ASSETNUM
HAVING
COUNT(A.ASSETNUM) > 1
The script returns correctly when there are duplicates, however when there are no duplicates, the table returns nothing.
If there are duplciates the output is
TableName ColumnName TotalRows PassFail
Plant.Asset ASSETNUM 1234 0
If there are no duplicates, the output is currently blank
TableName ColumnName TotalRows PassFail
If there are no duplicates, the output should be
TableName ColumnName TotalRows PassFail
Plant.Asset ASSETNUM 0 1
You want case expression :
SELECT 'Plant.Asset' AS [TableName], A.ASSETNUM AS [ColumnName], COUNT(1) AS TotalRows,
(CASE WHEN COUNT(1) > 1 THEN 0 ELSE 1 END) AS PassFail
FROM Plant.Asset a INNER JOIN
Plant.Loc AS B
ON A.LOCATION = B.LOCATION
GROUP BY A.ASSETNUM;
You've tagged this with Stored Procedure so I assume this SELECT is part of a stored procedure. A quick and easy way to handle this would be to INSERT the results of your query into a table variable or temp table:
INSERT INTO #ResultTable (TableName, ColumnName, TotalRows, PassFail)
SELECT
'[Plant.Asset]' AS TableName
,'[ASSETNUM]' AS ColumnName
,COUNT(1) AS TotalRows
,0 AS PassFail
FROM Plant.Asset a
INNER JOIN Plant.Loc AS B ON A.LOCATION = B.LOCATION
GROUP BY
A.ASSETNUM
HAVING
COUNT(A.ASSETNUM) > 1;
Then check that table and either return it or your default result, since you have a static result that you want to return if there are no duplicates:
IF (SELECT COUNT(*) FROM #ResultTable > 0)
SELECT * FROM #ResultTable;
ELSE
SELECT
'[Plant.Asset]' AS TableName
,'[ASSETNUM]' AS ColumnName
,0 AS TotalRows
,1 AS PassFail
I have two SQL Database table namely
Cust_Table(CustID, CustName, custAddrs, CustMob, CustOpBal)
And
Trans_Table(TransId, CustID, TransAmt, TransType(bool dr/cr), Msg, TansDate)
Now I need the SQL Query for getting Statement like (Bank Passbook) for a particular
Customer ID?
Date Message Dt_Amount Cr_Amount Balance
Iam using the following query
SELECT t1.Trans_Date, t1.Trans_Msg,
(CASE WHEN t1.Trans_Type=1 THEN 'Cr' ELSE 'Dr' END) as Trans_Type,
t1.Trans_Amount,
SUM(t2.Trans_Amount*case when t2.trans_type = '1' then 1 else -1 end) as Balance
FROM [LNLCredit].[dbo].[Trans_Table] t1
INNER JOIN [LNLCredit].[dbo].[Trans_Table] t2
ON t1.cust_id = t2.cust_id AND t1.trans_id >= t2.Trans_ID
WHERE t1.Cust_ID=2
GROUP BY t1.cust_id,t1.trans_id,t1.trans_type,t1.Trans_Amount,t1.Trans_Date,t1.Trans_Msg;
Its working fine.
But I also want to add Opening Balance (from Cust_Table) to the above solution.
Please Help??????
Try this..
SELECT t1.Trans_Date, t1.Trans_Msg,
(CASE WHEN t1.Trans_Type=1 THEN 'Cr' ELSE 'Dr' END) as Trans_Type,
t1.Trans_Amount,
SUM(t2.Trans_Amount*case when t2.trans_type = '1' then 1 else -1 end) as Balance,
c.CustOpBal
FROM [LNLCredit].[dbo].[Trans_Table] t1
INNER JOIN [LNLCredit].[dbo].[Trans_Table] t2
ON t1.cust_id = t2.cust_id AND t1.trans_id >= t2.Trans_ID
INNER JOIN Cust_Table C on C.cust_id = t1.cust_id
WHERE t1.Cust_ID=2
GROUP BY t1.cust_id,t1.trans_id,t1.trans_type,t1.Trans_Amount,
t1.Trans_Date,t1.Trans_Msg,C.CustOpBal;
You need to add an extra INNER JOIN and add openingBalance column to GROUP BY and SELECT
I've buit a CTE and want to update an existing physical table based on results from the CTE.
;WITH CTE
AS
(
Select t.ID As [CTE_ID]
,count(distinct case when e.Department='M' then t.ID else null end) as M_Marketing
,count(distinct case when e.Department='S' then t.ID else null end) as S_Sales
,count(distinct case when e.Department='U' then t.ID else null end) as U_Utilization
,count(distinct case when e.Department=' ' then t.ID else null end) as No_NoDepartment
From dbo.Table t (nolock)
Left Join dbo.ClearedEmployee ce (nolock) ON t.ID = ce.building_fk
Join dbo.Employee e (nolock) ON ce.employee_fk = e.employee_pk
Group By t.ID
)
Select *, t.ID
From CTE c (nolock)
FULL JOIN dbo.Table t (nolock) ON t.ID=c.[CTE_ID]
Order By t.ID ASC;
I want to updated my existing table with the results produced BY THE CODE ABOVE for each ID within the CTE And I'm using the code below:
UPDATE dbo.Table t
SET Marketing=M_Marketing,
Sales=S_Sales,
Utilization=U_Utilization,
NoDepartment=No_NoDepartment
FROM CTE
But this code updates all rows (all rows with unique IDs) of Marketing, Sales, Utilization and NoDepartment columns with values that present in the first row of the CTE result set. Basicaly I cannot really use CTE true result set to update the table.
UPDATE t
SET t.Marketing=M_Marketing,
t.Sales=S_Sales,
t.Utilization=U_Utilization,
t.NoDepartment=No_NoDepartment
FROM CTE C JOIN Table T ON T.ID=C.CTE_ID
In your update statement, you need to tell SQL Server how to map the data from the CTE to the data from the table.
I am trying to implement a way to replace "dynamic SQL" of WHERE clause.
That is, to create a temp table, "#FilterTable", which contains my WHERE's name and value.
Then, I use "left join" to map my target table #Hotel with #FilterTable.
However, I got an error when using the following code:
DECLARE #filterName varchar(50)='Id',
#filterValue int =13
CREATE TABLE #Hotel (Id varchar(50), DisplayName varchar(100))
CREATE TABLE #FilterTable (Name varchar(50), Value varchar(100))
INSERT INTO #Hotel(Id,DisplayName) VALUES ('1','California Inn'), ('13','Hilton Hotel')
INSERT INTO #FilterTable(Name,Value) VALUES ('Id','13'),('DisplayName','Hotel')
SELECT a.*
FROM #Hotel a WITH(NOLOCK)
LEFT JOIN #FilterTable b WITH(NOLOCK)
ON #filterName= b.Name
AND
CASE b.Name
WHEN 'Id' THEN CONVERT(varchar(10), a.Id) = b.Value
WHEN 'DisplayName' THEN a.DisplayName like b.Value END
DROP Table #Hotel
DROP Table #FilterTable
It always shows error in
WHEN 'Id' THEN CONVERT(varchar(10), a.Id) = b.Value
WHEN 'DisplayName' THEN a.DisplayName like b.Value END
I know if I change to
WHEN 'DisplayName' THEN CONVERT(varchar(10), a.Id) END = b.Value
, it will pass, but there is no way to add the second condition in "WHEN" clause under this situation.
Does anyone know what is the correct syntax to put those two "WHEN" clause togather?
My db version is SQL SERVER 2014 Enterprise.
Thank you.
Your syntax for CASE is incorrect. You're using it like a switch statement in C, Java, etc. You don't say case against a value, then switch on the value. Rather, it's like an if statement where each condition is independent.
SELECT a.*
FROM #Hotel a WITH(NOLOCK)
LEFT JOIN #FilterTable b WITH(NOLOCK)
ON #filterName= b.Name
AND
CASE
WHEN b.Name = 'Id' AND CONVERT(varchar(10), a.Id) = b.Value THEN 1
WHEN b.Name = 'DisplayName' AND a.DisplayName like b.Value THEN 1
ELSE 0
END = 1
This says, if b.Name is ID and the convert pattern matches, the row matches, or if b.Name is DisplayName and the display name is like b.Value, the row matches.
Give that a try.
I do have to point out that this is likely to not scale well given multiple rows. You should really have a separate query for each case so that SQL Server can use the appropriate indexes and statistics.
In your code:
WHEN 'Id' THEN CONVERT(varchar(10), a.Id) = b.Value
WHEN 'DisplayName' THEN a.DisplayName like b.Value END
= b.Value and like b.Value equals = b.Value. If you want to use LIKE you have to add: like '%' + b.Value + '%'
But if it doesn't mean then you can use:
b.Value = CASE b.Name
WHEN 'Id' THEN CONVERT(varchar(10), a.Id)
WHEN 'DisplayName' THEN a.DisplayName END
I have SQL query
; with cte as
(
SELECT
PARSENAME(REPLACE(replace(replace(replace(replace(dbo.IDENTITY_MAP.Name, 'My Company\', ''), '-VLAN2', ''), '.VLAN2\', ''), '.Instr\', '') , '\' , '.'), 1) as "Site",
Count (CASE
WHEN dbo.SEM_AGENT.AGENT_VERSION LIKE '11.%' THEN 1
END) AS 'SEP-11',
Count (CASE
WHEN dbo.SEM_AGENT.AGENT_VERSION LIKE '12.%' THEN 1
END) AS 'SEP-12',
FROM
dbo.sem_computer
INNER JOIN
[dbo].[V_SEM_COMPUTER] ON [dbo].[V_SEM_COMPUTER].COMPUTER_ID = SEM_COMPUTER.COMPUTER_ID
WHERE
dbo.IDENTITY_MAP.Name NOT LIKE '%Servers%'
GROUP BY
PARSENAME(REPLACE(replace(replace(replace(replace(dbo.IDENTITY_MAP.Name,'My Company\',''),'-VLAN2',''),'.VLAN2\',''),'.Instr\','') , '\' , '.'),1)
)
select *
from cte
join SEPM_site ss on cte.Site = ss.Site
That gives output I am looking for ------ almost i.e.
Site SEP-11 SEP-12 Rackcode Circuit Site
I only need one column for Site.
I tried recreating a temporary table with the columns, and dropping it, i.e.
; with cte as (SELECT ...)
select * into temptable
from cte
join SEPM_site ss
on cte.Site = ss.Site
alter table temptable
drop column cte.Site
select * from temptable
drop table temptable
But I get error
Incorrect syntax near '.'
And if I don't specify which table Site is from, I get error,
Column names in each table must be unique. Column name 'Site' in table 'temptable' is specified more than once.
But that's why I am trying to remove duplicate column!
Thanks!
Just specify the columns you want in your select statement:
select cte.Site, cte.[SEP-11], cte.[SEP-12], ss.Rackcode, ss.Circuit
from cte
join SEPM_site ss
on cte.Site = ss.Site
You can also select all columns in cte and just the ones you want in ss:
select cte.*, ss.Rackcode, ss.Circuit
from cte
join SEPM_site ss
on cte.Site = ss.Site