Return row only if one occurance - sql-server

I'm trying to fetch all the Id rows that only has zeroes.
Id | valid
---| ------
1 | 0
1 | 1
2 | 0
2 | 0
3 | 1
4 | 0
4 | 1
5 | 0
6 | 1

SELECT ID
FROM myTable
WHERE Valid = 0
AND ID NOT IN (
SELECT ID
FROM myTable
WHERE Valid != 0
)

Yet another option
Select A.*
From YourTable A
Join (
Select ID
From YourTable
Group By ID
Having min(valid)=0 and max(valid)=0
) B
on A.ID=B.ID
Returns
Id valid
2 0
2 0
5 0

You can use LEFT JOIN with NULL check to achieve your expected result.
Sample execution with given data:
DECLARE #TestTable TABLE (Id int, valid int);
INSERT INTO #TestTable (Id, valid)
VALUES (1, 0), (1, 1), (2, 0), (2, 0), (3, 1), (4, 0), (4, 1), (5, 0), (6, 1);
SELECT T1.*
FROM #TestTable T1
LEFT JOIN #TestTable T2 ON T2.Id = T1.Id AND T2.valid <> 0
WHERE T2.Id IS NULL
Result:
Id valid
----------
2 0
2 0
5 0
If you want Ids only, use SELECT DISTINCT T1.Id.

If your Id has only zeroes that sum of valid would be zero. Here is an example of the code.
drop table if exists dbo.Table03;
create table dbo.Table03 (
Id int
, valid int
);
insert into dbo.Table03 (Id, valid)
values (1, 0), (1, 1), (2, 0), (2, 0), (3, 1), (4, 0), (4, 1), (5, 0), (6, 1);
select
t.Id
from dbo.Table03 t
group by t.Id
having SUM(t.valid) = 0

Related

How to query for all groups containing one required element and at least one optional element in sqlite3

Problem & expected result
Suppose I have the following table t:
id f_id col1
---------- ---------- ----------
1 1 B
2 1 C
3 2 A
4 2 C
5 2 D
6 2 E
7 3 A
8 3 D
9 3 E
10 4 A
11 4 B
12 5 C
13 5 D
I would like to select all distinct f_id such that col1 contains one of the following combinations of values:
A and C
A and D
A and C and D
The expected result would therefore be:
f_id
----------
2
3
Own attempt
Based on a previous question I tried the following query
SELECT f_id
FROM t
WHERE (col1 IN ('A', 'C')) or (col1 in ('A', 'D'))
GROUP BY f_id
HAVING COUNT(distinct col1) >= 2;
This query however also matches with groups which contain C and D, but not A. I do not want this because A is important. The above query results in the following:
f_id
----------
2
3
5
How do I obtain the desired result?
Original script
For convenience, here is the code to generate the original table:
drop table if exists t;
CREATE TABLE t (id INTEGER, f_id INTEGER, col1 VARCHAR(1));
INSERT INTO t (id, f_id, col1) VALUES
(1, 1, 'B'),
(2, 1, 'C'),
(3, 2, 'A'),
(4, 2, 'C'),
(5, 2, 'D'),
(6, 2, 'E'),
(7, 3, 'A'),
(8, 3, 'D'),
(9, 3, 'E'),
(10, 4, 'A'),
(11, 4, 'B'),
(12, 5, 'C'),
(13, 5, 'D')
;
First filter the rows of the table so that only rows containing 'A' or 'C' or 'D' in col1 are returned and group by f_id.
Finally set the conditions in the HAVING clause, so that you get only f_ids that contain at least 1 'A' and any of the other 2:
SELECT f_id
FROM t
WHERE col1 IN ('A', 'C', 'D')
GROUP BY f_id
HAVING SUM(col1 = 'A') > 0
AND COUNT(DISTINCT col1) > 1
If there are no duplicates in col1 for each f_id you may change COUNT(DISTINCT col1) > 1 with COUNT(*) > 1.
Or, with EXISTS:
SELECT t1.f_id
FROM t t1
WHERE t1.col1 = 'A'
AND EXISTS (
SELECT 1
FROM t t2
WHERE t2.f_id = t1.f_id AND t2.col1 IN ('C', 'D')
)
See the demo.
Assuming that the order of the combinations is not important:
select f_id, group_concat(col1, '') agg
from t
GROUP BY f_id
HAVING (agg LIKE '%A%' AND agg LIKE '%C%')
OR (agg LIKE '%A%' AND agg LIKE '%D%');
There might be a better way to compare (with regex for example).

How to select each top 1 value from the table based on catgory_id in SQL Server

How to select top 1 value from the table based on category_id?
I have a table like this. Please help me.
Table 1
ID Name category_id
-------------------
1 A 1
2 B 1
3 c 1
4 d 2
5 e 2
6 f 2
7 g 3
8 h 3
9 i 3
How to get the below mentioned output from table 1?
ID Name category_id
--------------------
1 A 1
4 d 2
7 g 3
CREATE TABLE #Table1
([ID] int, [Name] varchar(1), [catgory_id] int)
;
INSERT INTO #Table1
([ID], [Name], [catgory_id])
VALUES
(1, 'A', 1),
(2, 'B', 1),
(3, 'c', 1),
(4, 'd', 2),
(5, 'e', 2),
(6, 'f', 2),
(7, 'g', 3),
(8, 'h', 3),
(9, 'i', 3)
;
SELECT [ID], [Name], [catgory_id]
FROM (
SELECT *
,ROW_NUMBER() OVER (
PARTITION BY [CATGORY_ID] ORDER BY [ID]
) AS RN
FROM #TABLE1
) A
WHERE RN = 1
output
ID Name catgory_id
1 A 1
4 d 2
7 g 3
SELECT TOP 1 WITH TIES [ID], [Name], [catgory_id]
FROM #Table1
ORDER BY
ROW_NUMBER() OVER (
PARTITION BY [CATGORY_ID] ORDER BY [ID] )

Aggregate count of different columns

There are two table:
Table a:
id name b_id1 b_id2 b_id3 b_id4
1 a 10 8 null null
2 b 3 4 8 10
3 c 10 5 4 null
Table B
b_id title
3 Value3
4 Value4
5 Value 5
8 Value 8
10 Value
Table A has F.K on b_id1,b_id2,b_id3,b_id4 to table B on b_id cloumn,
We are going to group on Title and count it.
something like following result:
Title Count
Value3 1
Value4 2
Value5 1
Value8 2
Value10 3
Null 3
Full working example:
DECLARE #Table1 TABLE
(
[id] INT
,[name] VARCHAR(1)
,[b_id1] INT
,[b_id2] INT
,[b_id3] INT
,[b_id4] INT
);
DECLARE #Table2 TABLE
(
[b_id] INT
,[title] VARCHAR(7)
);
INSERT INTO #Table1 ([id], [name], [b_id1], [b_id2], [b_id3], [b_id4])
VALUES (1, 'a', 10, 8, NULL, NULL)
,(2, 'b', 3, 4, 8, 10)
,(3, 'c', 10, 5, 4, NULL);
INSERT INTO #Table2 ([b_id], [title])
VALUES (3, 'Value3')
,(4, 'Value4')
,(5, 'Value 5')
,(8, 'Value 8')
,(10, 'Value');
SELECT T2.[title]
,COUNT(*)
FROM
(
SELECT [b_id1]
FROM #Table1
UNION ALL
SELECT [b_id2]
FROM #Table1
UNION ALL
SELECT [b_id3]
FROM #Table1
UNION ALL
SELECT [b_id4]
FROM #Table1
) DS
LEFT JOIN #Table2 T2
ON DS.[b_id1] = T2.[b_id]
GROUP BY T2.[title];
One way would be like below:Demo Here
;with cte
as
(select title,count(b_id) as val from table1 t
join
table2 t2
on t.id=t2.b_id
or
t.b_id1=t2.b_id
or
t.b_id2=t2.b_id
or
t.b_id3=t2.b_id
or
t.b_id4=t2.b_id
group by title
)
select * from cte
union all
select null,sum(case
when b_id1 is null then 1 else 0 end)+
sum(case
when b_id2 is null then 1 else 0 end)
+sum(case
when b_id3 is null then 1 else 0 end)
+sum(case
when b_id4 is null then 1 else 0 end)
from table1
output:
Value 3
Value 5 1
Value 8 2
Value3 2
Value4 2
NULL 3

How to create a Matrix table on SQL from another table

I have the following table with the following columns.
-------------------------------------
Column1 | Column2 | TotalCount
--------------------------------------
1 1 40
1 2 50
2 1 10
2 2 60
Also, I have another table that is related to Column1 where 1 is X and 2 is Y and same for Column2 where 1 is A and 2 is B
I am trying to come up with a SQL statement that basically gives me some view like...
--------------------
ColumnName | A | B
--------------------
X 40 50
Y 10 60
Any idea how can I achieve that? I've been trying to pivot the data with no luck.
Thanks!
Full working example:
DECLARE #DataSource TABLE
(
[Column1] TINYINT
,[Column2] TINYINT
,[TotalCount] TINYINT
);
INSERT INTO #DataSource ([Column1], [Column2], [TotalCount])
VALUES (1, 1, 40)
,(1, 2, 50)
,(2, 1, 10)
,(2, 2, 60);
SELECT *
FROM
(
SELECT IIF([Column1] = 1, 'X', 'Y') AS [ColumnName]
,IIF([Column2] = 1, 'A', 'B') AS [Column2]
,[TotalCount]
FROM #DataSource
) DS
PIVOT
(
MAX([TotalCount]) FOR [Column2] IN ([A], [B])
) PVT;
Using conditional aggregation:
WITH tbl AS(
SELECT * FROM ( VALUES
(1, 1, 40), (1, 2, 50),
(2, 1, 10), (2, 2, 60)
)t(Column1, Column2, TotalCount)
)
SELECT
ColumnName = CASE WHEN Column1 = 1 THEN 'X' ELSE 'Y' END,
A = MAX(CASE WHEN Column2 = 1 THEN TotalCount END),
B = MAX(CASE WHEN Column2 = 2 THEN TotalCount END)
FROM tbl
GROUP BY Column1
RESULT:
ColumnName A B
---------- ----------- -----------
X 40 50
Y 10 60

How can I recursively calculate a value

I have this table.
Bundles
id | parent_id | quantity
1 | 0 | 1
2 | 1 | 4
3 | 2 | 5
I want to get the total quantity of a bundle with id 3, which is 1 * 4 * 5 = 20 items
Can this be done with a single query?
Here's a solution using CTE:
Setup:
CREATE TABLE Table1
(id int, parent_id int, quantity int)
;
INSERT INTO Table1
(id, parent_id, quantity)
VALUES
(1, 0, 1),
(2, 1, 4),
(3, 2, 5),
(4, 0, 7),
(5, 4, 10)
;
CTE to return total of id=3 and it's parent items:
;WITH myCTE AS
(
SELECT id, parent_id, quantity
FROM Table1
WHERE id = 3
UNION ALL
SELECT T.id, T.parent_id, T.quantity
FROM Table1 T
JOIN myCTE C ON T.id = C.parent_id
)
SELECT EXP(sum(log(quantity)))
FROM myCTE
Demo SQL Fiddle
Multiplication method for values in a column, SELECT EXP(sum(log(quantity))), taken from here.

Resources