To 'flag' a specific condition in SQL query - sql

I have a result set in the below format and I need to flag "GroupColumn"
-------------------------------------------------------------------
ID GroupColumn ConditionCol1 ConditionCol2
-------------------------------------------------------------------
1 101 ABC 99
2 101 DEF 99
3 102 ABC 01
4 102 DEF 01
5 103 ABC 02
6 103 DEF 99
7 104 DEF 02
8 104 DEF 99
First of the I need to flag the data based on "GroupColumn", with in this "GroupColumn" I am looking to satisfy Condition of "ABC" from one row and "99" from another row but not necessarily from the same row.
I looking to get a final result set some thing like this for the "Output" column
-------------------------------------------------------------------
ID GroupColumn ConditionCol1 ConditionCol2 Output
-------------------------------------------------------------------
1 101 ABC 99 Satisfied
2 101 DEF 99 Satisfied
3 102 ABC 01
4 102 DEF 01
5 103 ABC 02 Satisfied
6 103 DEF 99 Satisfied
7 104 DEF 02
8 104 DEF 99

You can do this using window functions:
select t.*,
(case when sum(case when conditioncol1 = 'ABC' then 1 else 0 end) over (partition by groupcolumn) > 0 and
sum(case when conditioncol2 = 99 then 1 else 0 end) over (partition by groupcolumn) > 0
then 'Satisfied'
end) as flag
from t;
An alternative is to use group by:
select t.*, tt.flag
from t join
(select groupcolumn, 'Satisfied' as flag
from t
where conditioncol1 = 'ABC' or conditioncol2 = 99
group by groupcolumn
having sum(case when conditioncol1 = 'ABC' then 1 else 0 end) > 0 and
sum(case when conditioncol2 = 99 then 1 else 0 end) > 0
) tt
on tt.groupcolumn = t.groupcolumn;

Assuming you are using SQL Server and you need to add Output column to your original table, you can try the following:
create table #temp
(GroupColumn int,ConditionCol1 varchar(20),ConditionCol2 int)
insert into #temp values (100,'ABC',99)
insert into #temp values (100,'DEF',99)
insert into #temp values (101,'ABC',02)
insert into #temp values (101,'DEF',99)
insert into #temp values (102,'DEF',99)
insert into #temp values (102,'DEF',99)
ALTER TABLE #temp
ADD [Output] varchar(10)
GO
;with cte(GroupColumn) as (
select GroupColumn
from #temp
where ConditionCol1 <> 'ABC'
and ConditionCol2 = 99
)
UPDATE t
SET [Output] = 'Satisfied'
FROM #temp t
INNER JOIN cte on t.GroupColumn = cte.GroupColumn
WHERE t.ConditionCol1 = 'ABC'
UPDATE t
SET [Output] = 'Satisfied'
FROM #temp t
WHERE [Output] is null
and t.GroupColumn in (Select GroupColumn from #temp where [Output]='Satisfied')
select * from #temp

Related

select data by passing a value in where clause if the value match then return that data otherwise return all data

select data by passing a value in where clause if the value match then return matches data otherwise return all data.
Consider following example
ID Name
1 ABC
2 DEF
3 GHI
4 JKL
When pass id = 1 the return row 1 when pass null value or 0 then return all data.
You can use analytical function as follows:
SELECT * FROM
(SELECT T.*,
SUM(CASE WHEN T.ID = <YOUR_VALUE(0,1,NULL, or any)> THEN 1 ELSE 0 END) OVER () AS SM
FROM YOUR_TABLE T)
WHERE SM = 0 OR ID = <YOUR_VALUE(0,1,NULL, or any)>
You need to replace <YOUR_VALUE(0,1,NULL)> with a value that you want to pass.
For values 0 and 1, results are as follows:
SQL> SELECT * FROM
2 (SELECT T.*,
3 SUM(CASE WHEN T.ID = 0 THEN 1 ELSE 0 END) OVER () AS SM
4 FROM YOUR_TABLE T)
5 WHERE SM = 0 OR ID = 0 ;
ID NAM SM
---------- --- ----------
1 ABC 0
2 DEF 0
3 GHI 0
4 JKL 0
SQL>
SQL>
SQL> SELECT * FROM
2 (SELECT T.*,
3 SUM(CASE WHEN T.ID = 1 THEN 1 ELSE 0 END) OVER () AS SM
4 FROM YOUR_TABLE T)
5 WHERE SM = 0 OR ID = 1;
ID NAM SM
---------- --- ----------
1 ABC 1
SQL>
You can use not exists:
select t.*
from t
where id = 1 or
not exists (select 1 from t t2 where t2.id = 1);
Or as a passed-in value:
select t.*
from t
where id = :input or
not exists (select 1 from t t2 where t2.id = :input);
Note that this works for NULL values as well, because the where in the subquery would evaluate to NULL if :input is NULL.

Arithmetic operation on row value

I have a table with the below data
Tid Did value
------------------
1 123 100
1 234 200
2 123 323
2 234 233
All tids have dids as 123 and 234. So for every tid having dids 123 and 234 I want to calculate value of did 123/value of did 234 * 100 i.e 100/200 * 100
For tid 2 it will be value of did 123/value of did 234 * 100 i.e 323/233 * 100
The output table will be
Tid result
------------------
1 100/200 * 100
2 323/233 * 100
Any help?
JOIN the "123" rows with the "234" rows:
select t123.tid, t123.value * 100 / t234.value
from
(select tid, value from tablename where value = 123) t123
join
(select tid, value from tablename where value = 234) t234
on t123.tid = t234.tid
JOIN, all in ON
select t123.tid, t123.value * 100 / t234.value
from tablename t123
join tablename t234 on t123.tid = t234.tid and t123.did = 123 and t234.did = 234
Here is the query. We can use inner join to achieve it.
SELECT T1.Tid,(T1.value/T2.value)*100 AS Result
FROM Table_1 AS T1
INNER JOIN
Table_1 AS T2
ON (T1.Tid = T2.Tid)
AND (T1.Did <> T2.Did)
AND T1.Did = 123
select tid,
100 * sum(case when did = 123 then value end) /
sum(case when did = 234 then value end)
from your_table
group by tid
having sum(case when did = 234 then value end) > 0

How to get records from SQL

i have to SQL server 2008 tables as below
Table A
ID int Not Null (primary ID)
No int NULL
Value int NULL
Flag nchar(10) NULL
Table B
ID int Not Null (primary ID)
No int NULL
Value int NULL
Flag nchar(10) NULL
and i Have below data in table A
ID No Value Flag
1 1 12 1
2 1 12 1
3 1 25 1
4 2 120 1
5 3 36 2
6 2 120 2
7 6 1 1
8 2 10 1
9 6 10 2
10 1 25 2
11 2 120 1
and there no records in table B
when i write below statement
SELECT dbo.A.No, SUM(dbo.A.Value) AS [IN], SUM(ISNULL(dbo.B.Value, 0)) AS OUT
FROM dbo.A LEFT OUTER JOIN
dbo.B ON dbo.A.NO = dbo.B.NO
WHERE (dbo.A.Flag = N'1')
GROUP BY dbo.A.No
I am getting below result
No IN OUT
1 49 0
2 250 0
6 1 0
When I add WHERE (dbo.A.Flag = N'1') AND (dbo.B.Flag = N'1')
nothing is coming..
my question is How to get records from table B as 0 when B not contains records or not find B.Id
UPDATE :
When i have data in table B Then records are coming.
Imran,
I think the below sql will help you.
SELECT A.No,
SUM(A.Value) AS [IN],
SUM(ISNULL(B.Value, 0)) AS [OUT]
FROM dbo.A A
LEFT JOIN dbo.B B ON A.No = B.No AND B.Flag = N'1'
WHERE A.Flag = N'1'
GROUP BY A.No
Try using this condition :-
WHERE (dbo.A.Flag = N'1') AND (dbo.B.Flag = ISNULL(N'1',0));
This might be helpful to you.

Retrieve data from sql column by splitting one column into two

ID DepID Status
------------------
000 54 0
000 12 1
141 14 0
141 56 1
000 12 0
000 89 1
I have the above table in which I have the depID. The following is the output I need:
ID DepOld DepNew
-------------------
000 54 12
141 14 56
000 12 89
Status of 0 means its old and 1 means new. How do I get the above output, considering it's in one table?
I can't use the IN clause.
I tried the following
SELECT
ID,
Max(CASE
WHEN Status = 0 THEN DepID
END) DepOld,
Max(CASE
WHEN Status = 1 THEN DepID
END) DepNew
FROM
tablename
GROUP BY
ID
but this the output I get
Id DepOld DepNew
--------------------
000 54 54
000 12 NULL
141 14 14
141 56 Null
if i pass depID=54 then this output is what i want
ID DepOld DepNew
000 54 12
You can use conditional aggregation:
select id,
max(case when status = 0 then DepID end) as DepOld,
max(case when status = 1 then DepID end) as DepNew
from table t
group by id;
If you'll only ever have two rows per ID, one with Status = 0 and the other with Status = 1, you could join the table to itself based on the ID column so you have both the old and new Department IDs available in a single row:
SELECT old.ID, old.DepID AS DepOld, new.DepID AS DepNew
FROM your_table old
INNER JOIN your_table new ON old.ID = new.ID AND new.Status = 1
WHERE old.Status = 0
Using Case statement and Max aggragate you can get the result.
CREATE TABLE #fast
(
ID VARCHAR(100),
DepID INT,
Status INT
)
INSERT INTO #fast
VALUES ( '000',54,0),
('000',12,1),
('141',14,0),
('141',56,1),
('000',12,0),
('000',89,1)
SELECT ID,
Max(CASE
WHEN Status = 0 THEN DepID
END) DepOld,
Max(CASE
WHEN Status = 1 THEN DepID
END) DepNew
FROM tablename
GROUP BY ID

Retrieve matching rows using join

This is a simplified version of my problem.
I have table like below
Id Name SNumber
100 XYZ 123
100 XYZ 123
101 ABC 123
103 QAZ 123
100 XYZ 971
100 XYZ 872
100 XYZ 659
102 PQR 145
102 PQR 707
103 QAZ 421
I want to count rows having Snumber as '123' ie Total column and rows having Snumber not as '123' i.e. otherTotal column
Id Name Total OtherTotal
100 XYZ 2 3
101 ABC 1 0
102 PQR 0 2
103 QAZ 1 1
What I am doing is using join
Select xx.*,otherTotal
From
( Select Id,Name,count(*) as Total
From table
Where Snumber like '123'
Group By id,name
)xx
Inner join
( Select Id,Name,count(*) as otherTotal
From table
Where Snumber not like '123'
Group By id,name
)yy
On xx.Id=yy.Id
But this will only return rows if particular Id has both Snumber as 123 and not as 123
Data returned is like below
Id Name Total OtherTotal
100 XYZ 2 3
103 QAZ 1 1
Now there is no guarntee that a particular Id will always have Snumber as 123 so I can't use Left or Right join. How to solve this quagmire ? Giggity
Try this:
SELECT id, name,
COUNT(CASE WHEN SNumber = 123 THEN 1 END) Total,
COUNT(CASE WHEN SNumber <> 123 THEN 1 END) OtherTotal
FROM t
GROUP BY id, name
ORDER BY id
Fiddle here.
select
Id, Name,
sum(case when SNumber = 123 then 1 else 0 end) as Total,
sum(case when SNumber <> 123 then 1 else 0 end) as OtherTotal
from Table1
group by Id, Name
order by Id
or
select
Id, Name,
count(*) - count(nullif(SNumber, 123)) as Total,
count(nullif(SNumber, 123)) as OtherTotal
from Table1
group by Id, Name
order by Id
sql fiddle demo
try this one.
DECLARE #TABLE TABLE (ID INT, NAME VARCHAR(40), SNUMBER INT)
INSERT INTO #TABLE
VALUES
(100 ,'XYZ', 123),
(100 ,'XYZ', 123),
(101 ,'ABC', 123),
(103 ,'QAZ', 123),
(100 ,'XYZ', 971),
(100 ,'XYZ', 872),
(100 ,'XYZ', 659),
(102 ,'PQR', 145),
(102 ,'PQR', 707),
(103 ,'QAZ', 421)
SELECT
ID,
NAME,
(
SELECT
COUNT(SNUMBER) FROM #TABLE B
WHERE
SNUMBER = '123' AND A.ID = B.ID
) AS TOTAL,
(
SELECT
COUNT(SNUMBER) FROM #TABLE B
WHERE
SNUMBER <> '123' AND A.ID = B.ID
) AS OTHERTOTAL
FROM
#TABLE A
GROUP BY ID, NAME