Sql Count by multiple Where condition - sql

i've really bad problem with this sql query.
base on my tables i need some thing like this result:
table1
Id | Type | Size |Count | OwnerId
___________________________________
1 A 1 12 1
2 A 2 12 1
3 B 1 14 1
4 B 1 20 1
5 A 1 12 2
6 A 1 17 2
table2
Id | name
_________
1 A
2 B
The Result
______________________
Name | Size1Type1 Count | Size2Type1 Count | Size1Type2 Count
thanks indeeeeed .

You did not specify what RDBMS you are using but you should be able to get the result by implementing an aggregate function with a CASE statement. This process is similar to a PIVOT:
select t2.name,
sum(case when t1.size = 1 and t1.type = 'a' then 1 else 0 end) Size1Type1Count,
sum(case when t1.size = 2 and t1.type = 'a' then 1 else 0 end) Size2Type1Count,
sum(case when t1.size = 1 and t1.type = 'b' then 1 else 0 end) Size1Type2Count,
sum(case when t1.size = 2 and t1.type = 'b' then 1 else 0 end) Size2Type2Count
from table1 t1
inner join table2 t2
on t1.ownerid = t2.id
group by t2.name
See SQL Fiddle with Demo
Result:
| NAME | SIZE1TYPE1COUNT | SIZE2TYPE1COUNT | SIZE1TYPE2COUNT | SIZE2TYPE2COUNT |
--------------------------------------------------------------------------------
| A | 1 | 1 | 2 | 0 |
| B | 2 | 0 | 0 | 0 |
If you want to include your count field, then you would use something like this:
select t2.name,
sum(case when t1.size = 1 and t1.type = 'a' then "Count" end) Size1Type1Count,
sum(case when t1.size = 2 and t1.type = 'a' then "Count" end) Size2Type1Count,
sum(case when t1.size = 1 and t1.type = 'b' then "Count" end) Size1Type2Count,
sum(case when t1.size = 2 and t1.type = 'b' then "Count" end) Size2Type2Count
from table1 t1
inner join table2 t2
on t1.ownerid = t2.id
group by t2.name;
See SQL Fiddle with Demo
Result:
| NAME | SIZE1TYPE1COUNT | SIZE2TYPE1COUNT | SIZE1TYPE2COUNT | SIZE2TYPE2COUNT |
--------------------------------------------------------------------------------
| A | 12 | 12 | 34 | (null) |
| B | 29 | (null) | (null) | (null) |
Or you could even perform multiple joins on the tables to get the result that you want:
select t2.name,
sum(t1_a1."count") Size1Type1Count,
sum(t1_a2."count") Size2Type1Count,
sum(t1_b1."count") Size1Type2Count,
sum(t1_b2."count") Size2Type2Count
from table2 t2
left join table1 t1_a1
on t1_a1.ownerid = t2.id
and t1_a1.size = 1
and t1_a1.type = 'a'
left join table1 t1_a2
on t1_a2.ownerid = t2.id
and t1_a2.size = 2
and t1_a2.type = 'a'
left join table1 t1_b1
on t1_b1.ownerid = t2.id
and t1_b1.size = 1
and t1_b1.type = 'b'
left join table1 t1_b2
on t1_b2.ownerid = t2.id
and t1_b2.size = 2
and t1_b2.type = 'b'
group by t2.name
See SQL Fiddle with Demo

SELECT Name, Type, Size, SUM(Count) AS 'Count' FROM Table1, Table2
WHERE Table1.OwnerID = Tabel2.Id
GROUP BY Name, Type, Size

Related

single column value in multiple columns

ID|Class | Number
--+------+---------
1 | 1 | 58.2
2 | 1 | 85.4
3 | 2 | 28.2
4 | 2 | 55.4
The desired result would be:
Column1 |Number | Column2 | Number
--------+-------+---------+---------
1 | 58.2 | 2 |28.2
1 | 85.4 | 2 |55.4
What would be the required SQL?
You can user row_number() and aggregate:
select 1, max(case when seqnum % 2 = 1 then number end),
2, max(case when seqnum % 2 = 0 then number end)
from (select t.*,
row_number() over (partition by class order by id) as seqnum
from t
) t
group by ceiling(seqnum / 2.0);
The aggregation uses arithmetic to put pairs of rows for each class into one row.
try this
SELECT 1 AS Column1,t2.Number,2 AS Column2,t1.Number
FROM
(
SELECT *
FROM test11
) t2
INNER JOIN
(
SELECT *
FROM test11
) t1
ON t1.Class = t2.Class
WHERE t1.ID < t2.ID
ORDER BY t1.ID DESC
Demo in db<>fiddle

How to get 2 values of same num to 2 separate columns

I got table like this:
num |type|value
--------------
1 | a | 5
1 | b | 7
3 | c | 9
2 | a | 6
2 | b | 9
and want this kind of result:
num| value (a) | value (b)
-------------------------
1 | 5 | 7
2 | 6 | 9
You can use a self-join which will also remove the rows with just one value (num = 3 in your sample data)
select t1.num, t1.value as value_a, t2.value as value_b
from the_table t1
join the_table t2 on t1.num = t2.num and t2.type = 'b'
where t1.type = 'a'
You can use GROUP BY and CASE, as in:
select
num,
max(case when type = 'a' then value end) as value_a,
max(case when type = 'b' then value end) as value_b
from t
group by num
I'd join the table on itself, once for a and once for b
SELECT a.num, a.value, b.value
FROM mytable a
JOIN mytable b ON a.num = b.num AND a.type = 'a' AND b.type = 'b'

Join column name with value from other table

SELECT id FROM Table2 t2
INNER JOIN Table1 t1
on t1.ordno = t2.ordno
and t1.testcode = t2.testcode
WHERE RN1 > 0
AND RN2 > 0
AND RN3 > 0
AND RN3 > 0
AND RN4 > 0
AND RN5 > 0
AND RN6 > 0
I only want to return the id from Table2 if a value from Table1 is >0 (column name from Table1 exists in Table2.RNVALUE). So in this case, I only want the first two rows of table2 to pop-up because they have a value in table1 which is greater then 0. Can anyone help me with a query to do this?
Table1:
+--------------------------------------------------------+
| ORDNO | TESTCODE | RN1 | RN2 | RN3 | RN4 | RN5 | RN6 |
+--------------------------------------------------------+
| 123 | 456 | 55 | 56 | 0 | 0 | null | null |
+--------------------------------------------------------+
Table2:
+----------------------------------+
| ORDNO | TESTCODE | RN_VALUE | ID |
+----------------------------------+
| 123 456 RN1 1 |
| 123 456 RN2 2 |
| 123 456 RN3 3 |
| 123 456 RN4 4 |
+----------------------------------+
I believe you want something like this:
SELECT t2.*
FROM Table2 t2 INNER JOIN
Table1 t1
ON t1.ordno = t2.ordno AND t1.testcode = t2.testcode
WHERE (RN1 > 0 AND t2.RN_VALUE = 'RN1') OR
(RN2 > 0 AND t2.RN_VALUE = 'RN2') OR
(RN3 > 0 AND t2.RN_VALUE = 'RN3') OR
(RN4 > 0 AND t2.RN_VALUE = 'RN4') OR
(RN5 > 0 AND t2.RN_VALUE = 'RN5') OR
(RN6 > 0 AND t2.RN_VALUE = 'RN6');
Having multiple columns with names like that suggests a poor data model. Perhaps these should be in separate rows, with one value per row.
select t2.*
from table2 t2
inner join (select ordno, testcode, 1 as rn, rn1 as val
union
select ordno, testcode, 2 as rn, rn2 as val
union
select ordno, testcode, 3 as rn, rn3 as val
union
select ordno, testcode, 4 as rn, rn4 as val
union
select ordno, testcode, 5 as rn, rn5 as val
union
select ordno, testcode, 6 as rn, rn6 as val
) t1
on t2.rn_value=t1.rn
and t2.ordno=t1.ordno
and t2.testcode=t1.testcode
where t1.val>0

Running multiple SET statements in CTE?

using SQL 2012
I have a CTE statement that give me incorrect results. Multiple records for each record_id may exist with different types. This seems to be skipping records and not updating all of them correctly:
WITH cte as (
SELECT
o.sname, o.type, o.record_id,
p.data1, p.data2, p.data3
FROM
table1 p
JOIN table2 o ON o.record_id = p.record_id
WHERE
o.record_id IN(1,2,3)
--AND (o.type = 123 or o.type = 456 or o.type = 789)
UPDATE cte
set data1 = (case when type = 123 then 1 else data1 end),
data2 = (case when type = 456 then 1 else data2 end),
data3 = (case when type = 378 then 1 else data3 end)
where type in (123,456,789)
Not sure why this happens.
What I am after is to look at only certain records and if a specific TYPE value exists, change the DATA value to 1 every time it is encountered for specific TYPES.
If I run the UPDATE part of the CTE this way, it works correctly, just not when together:
UPDATE cte
set data1 = (case when type = 123 then 1 else data1 end),
where type in (123)
UPDATE cte
set data2 = (case when type = 456 then 1 else data2 end)
where type in (456)
UPDATE cte
set data3 = (case when type = 789 then 1 else data3 end)
where type in (789)
Whats wrong?
Here are Tables and desired outputs:
TABLE1
record_id |type |sname
------------|-------|-----|
1 |123 |alpha
2 |123 |alpha
2 |456 |beta
3 |456 |beta
3 |789 |gamma
Table 2 is originally all zeros
Desired Output:
TABLE2
record_id| data1| data2| data3|
---------|-------|-------|-------|
1 |1 | 0 | 0
2 |1 | 1 | 0
3 |0 | 1 | 1
Actual Output:
TABLE2
record_id| data1| data2| data3|
---------|-------|-------|-------|
1 |1 | 0 | 0
2 |1 | 0 | 0
3 |0 | 1 | 0
Thanks,
MP
You can simply use aggregation in a subquery to check which type exists for a given record_id and then multitable update like this:
update t2
set t2.data1 = t1.data1,
t2.data2 = t1.data2,
t2.data3 = t1.data3
from table2 t2
join (
select record_id,
max(case when type = 123 then 1 else 0 end) as data1,
max(case when type = 456 then 1 else 0 end) as data2,
max(case when type = 789 then 1 else 0 end) as data3
from table1
group by record_id
) t1
on t1.record_id = t2.record_id;
Demo
Another way is using correlation with EXISTS:
update t2
set data1 = case when exists (select 1 from table1 t1 where t1.record_id = t2.record_id and t1.type = 123) then 1 else 0 end,
data2 = case when exists (select 1 from table1 t1 where t1.record_id = t2.record_id and t1.type = 456) then 1 else 0 end,
data3 = case when exists (select 1 from table1 t1 where t1.record_id = t2.record_id and t1.type = 789) then 1 else 0 end
from table2 t2;
Demo 2

Remove and Identify Duplicate Records in SQL

I have some sample records below that I need to use the CASE WHEN statement to remove and identify the duplicate records in SQL.
Quantity Values Desc event ID
1 5 Blue 12550 577
1 5 bluee 12550 525
2 10 blu 12550 535
i would like to use a case statement to show the duplicate indicators such as:
Dup_Quantity Dup_Value Dup_Desc Quantity Values Desc event ID
Y Y N 1 5 Blue 12550 577
Y Y N 1 5 Bluee 12550 525
however, after using this script, the result still shows as:
Dup_Quantity Dup_Value Dup_Desc Quantity Values Desc event ID
Y Y N 1 5 Blue 12550 577
Y Y N 1 5 Bluee 12550 525
Y N N 2 10 Blu 12550 535
SELECT DISTINCT
CASE WHEN a.Quantity = b.Quantity THEN 'Y' ELSE 'N' END AS "Dup_Quantity",
CASE WHEN a.Values = b.Values THEN 'Y' ELSE 'N' END AS "Dup_Value",
CASE WHEN a.Desc = b.Desc THEN 'Y' ELSE 'N' END AS "Dup_Desc"
FROM Table1 a
INNER JOIN Table1 b ON a.event = b.event
WHERE (a.Quantity = b.Quantity OR a.Values = b.Values OR a.Desc = b.Desc)
AND a.ID <> b.ID
Basically, record with ID 535 stills shows up in the result. Would someone Please give me some pointers?
SQL Fiddle
MS SQL Server 2012 Schema Setup:
CREATE TABLE Table1
([Quantity] int, [Values] int, [Desc] varchar(5), [event] int, [ID] int)
;
INSERT INTO Table1
([Quantity], [Values], [Desc], [event], [ID])
VALUES
(1, 5, 'Blue', 12550, 577),
(1, 5, 'bluee', 12550, 525),
(2, 10, 'blu', 12550, 535)
;
Query 1:
SELECT
CASE WHEN (SELECT COUNT(*)
FROM Table1 t2
WHERE t1.Quantity = t2.Quantity AND
t1.ID <> t2.ID AND t1.event = t2.event) > 0
THEN 'Y' ELSE 'N' END AS Dup_Quantity,
CASE WHEN (SELECT COUNT(*)
FROM Table1 t2
WHERE t1."Values" = t2."Values" AND
t1.ID <> t2.ID AND t1.event = t2.event) > 0
THEN 'Y' ELSE 'N' END AS Dup_Value,
CASE WHEN (SELECT COUNT(*)
FROM Table1 t2
WHERE t1."Desc" = t2."Desc" AND
t1.ID <> t2.ID AND t1.event = t2.event) > 0
THEN 'Y' ELSE 'N' END AS Dup_Desc,
*
FROM Table1 t1
WHERE
(SELECT COUNT(*)
FROM Table1 t2
WHERE t1.Quantity = t2.Quantity AND
t1.ID <> t2.ID AND t1.event = t2.event) > 0
OR
(SELECT COUNT(*)
FROM Table1 t2
WHERE t1."Values" = t2."Values" AND
t1.ID <> t2.ID AND t1.event = t2.event) > 0
OR
(SELECT COUNT(*)
FROM Table1 t2
WHERE t1."Desc" = t2."Desc" AND
t1.ID <> t2.ID AND t1.event = t2.event) > 0
Results:
| DUP_QUANTITY | DUP_VALUE | DUP_DESC | QUANTITY | VALUES | DESC | EVENT | ID |
|--------------|-----------|----------|----------|--------|-------|-------|-----|
| Y | Y | N | 1 | 5 | Blue | 12550 | 577 |
| Y | Y | N | 1 | 5 | bluee | 12550 | 525 |
Your query returns:
Dup_Quantity Dup_Value Dup_Desc
Y Y N
However I don't get what you want to do here, the correct version of it is:
SELECT
CASE WHEN a."Quantity" = b."Quantity" THEN 'Y' ELSE 'N' END AS "Dup_Quantity",
CASE WHEN a."Values" = b."Values" THEN 'Y' ELSE 'N' END AS "Dup_Value",
CASE WHEN a."Desc" = b."Desc" THEN 'Y' ELSE 'N' END AS "Dup_Desc",
a.*
FROM Table1 a
INNER JOIN Table1 b ON b.event = a.event
WHERE (a."Quantity" = b."Quantity" OR a."Values" = b."Values" OR a."Desc" = b."Desc")
AND a.ID <> b.ID
If you want to get duplicated rows in terms of Quantity, Values and Desc:
SELECT
a.*
FROM Table1 a
INNER JOIN Table1 b ON b.event = a.event
WHERE (a."Quantity" = b."Quantity" AND a."Values" = b."Values" AND a."Desc" = b."Desc")
AND a.ID <> b.ID