How to create a select query that selects a repeating value in one of colums only once from multiple rows(example inside) - sql

This is for example what I have(This is the result of a select query from different tables by different conditions let's call it Select X) :
ID c2 c3 c4
1 A de ys
2 A rq pm
3 B rq qs
I want a query that will give only one row with a certain value in c2, for example:
ID c2 c3 c4
1 A de ys
3 B rq qs
or
ID c2 c3 c4
2 A rq pm
3 B rq qs
I know how to do that using a data structure but it's more complicated, I wonder if there is a way to do that using a query?
Edit : This is what I tried and it gives error : " Syntax error in From clause "
( If it matters X = SELECT Responses.ID,Responses.PostID,Responses.Responding,Posts.ID,Posts.UserID,Users.ID,Users.Username FROM Responses,Posts,Users WHERE Responses.PostID =3 and Posts.ID = Responses.PostID AND Responses.Responding = Users.ID)
SELECT(Select X).*
FROM (Select X) as (Select X)
JOIN (
SELECT MIN(ID) AS ID, Users.ID
FROM (Select X)
GROUP BY Users.ID
) AS t2 ON (Select X).ID = t2.ID
EDIT : well I'll leave this open but at the end I chosen the data structure way not the query way.

Something like this:
SELECT t1.*
FROM mytable as t1
JOIN (
SELECT MIN(ID) AS ID, c2
FROM mytable
GROUP BY c2
) AS t2 ON t1.ID = t2.ID
This will pick the row having the minimum ID value within a group of same c2 values. You can use MAX aggregate function to get the second result set.
Note: I've made the assumption that ID is the PK of your table.
Edit:
You can use a derived table from you SELECT query like this:
SELECT t1.*
FROM (SELECT X ...) as t1
JOIN (
SELECT MIN(ID) AS ID, c2
FROM (SELECT X ...) AS t
GROUP BY c2
) AS t2 ON t1.ID = t2.ID

Related

How to select groups which has only the values we want and not select it if it also has other values in SQL

id
code
value
A
cod
2
A
buy
34
A
cod
4
B
cod
44
B
F
23
C
thk
45
C
cod
33
C
F
31
D
cod
22
In this table for example, I want those groups of id which has 'code' column value as ONLY cod or F. so query should return values of id = B and nothing else. ( Not even values with id = C because id=C also has 'thk' in code , not even id= D, and output should have ids with ONLY the mentioned two values)
expected output
id
code
value
B
cod
44
B
F
23
You want all rows for the ID of which not exists a forbidden row:
select id, code, value
from mytable
where not exists
(
select null
from mytable forbidden_row
where forbidden_row.id = mytable.id
and forbidden_row.code not in ('cod', 'F')
);
One of approaches with nested query
SELECT ID,Code, value FROM (
select ID, Code,
(SELECT count(*) FROM TableA a where Code = 'cod' and a.ID = TableA.ID) Cod,
(SELECT count(*) FROM TableA a where Code = 'F' and a.ID = TableA.ID) F,
(SELECT count(*) FROM TableA a where Code not in ('F','cod') and a.ID = TableA.ID) Other,
Value
from TableA
) SOURCE
WHERE Cod <> 0 AND F <> 0 and Other = 0
We can achieve this using CTE. Check this,
-- Split the two record category first, then check cod Or F condition.
WITH Count2 AS (
SELECT id
FROM YourTable
GROUP BY id
HAVING COUNT(id) = 2
),
codORF AS (
SELECT id, code, COUNT(id) FROM YourTable T1
LEFT JOIN Count2 T2 On T1.id = T2.id
WHERE code = 'cod' OR code = 'F'
GROUP BY id, code
Having COUNT(id) = 1
)
-- Finally to take all values
SELECT T1.*
FROM YourTable T1
INNER JOIN codORF T2 ON T1.id = T2.id
with main as (
select *, count(id) over(partition by id order by id) as total_rows
from sample
), next_and_before as (
select *,
COALESCE(lag(code) over(partition by id order by id),lead(code) over(partition by id order by id)) as before_next
from main where total_rows <= 2
)
select * from next_and_before
where lower(trim(concat(code,before_next)))in('codf','fcod','cod','f')
Its a bit of hacky solution:
first you are filtering out all the rows that have less than or equal to 2 rows, since there could be cases where you only have one row per id with a code value = 'f' or 'cod', if you don't want that then simply change the last part to: in ('codf','fcod')
then out of two rows, you are looking at the next and before value and checking if it contains other than 'f' or 'cod'
where clause will filter those out if they exist
Test Results from the link below:
Results of sample data

Only return rows if all items with the same ID has all the same value in another column

I am trying to figure out a way to identify all ID's that only contain all of the same value in another column.
In the example above Looking for all SubID's that are inactive it would only return rows for C2 (ID's 2, 5, & 6).
Sample Data :
You use not exists :
select t.*
from table t
where not exists (select 1 from table t1 where t1.subid = t.subid and t1.status = 'Active');
EDIT : If you want to get the subids which have same status then you can do :
select t.*
from table t
where not exists (select 1 from table t1 where t1.subid = t.subid and t1.status <> t.status);
use group by and sub-query
select t.* from
(select subid,status from t t1
group by subid,status
having count(*)>1
) as t1
inner join t on t.subid=t1.subid and t.status=t1.status

SQL query that finds repeated data in one column with different data in a second column

Let's say I have data that looks like this:
ID Date Data
A D1 123
A D1 456
A D2 123
What I'm looking for is a select statement that will pull all rows where ID and Date are repeated as a pair, but the data doesn't match. In this case, it would return the top two rows, because ID A and Date D1 are repeated as a pair, but the Data is different. The third row would not be returned because the ID and Date combination are not repeated.
There are several ways to do this. Here's one option using exists:
select *
from yourtable t
where exists (
select 1
from yourtable t2
where t.id = t2.id and t.date = t2.date and t.data <> t2.data
)
SELECT d.Id ,
d.Date ,
d.Data
FROM YourTable d
INNER JOIN ( SELECT Id ,
Date
FROM YourTable
GROUP BY Id ,
Date
HAVING COUNT(*) > 1
) a ON a.Id = d.Id

Select rows from table such that sum of computed values of their column is less than given limit

I have a table myTable of the following structure:
id: int PRIMARY KEY
number: int
I'd like to randomly select 3 rows at most from myTable under the conditions:
Three rows at most should be selected
We should select id and a value calculated as 0,3*RAND()*number converted to INT. The alias of the computed column is randomValue
Only rows with randomValue>0 should be included in the result
Sum of randomValues should be less than given treshold, say 60.
So far, I've written this:
SELECT TOP 3 id,randomValue
FROM(
SELECT id, CONVERT(INT,(0.3*RAND()*number)) AS randomValue
FROM myTable
WHERE number>0
) AS D
WHERE randomValue>0
ORDER BY NEWID()
The code above selects at most 3 random rows where randomValue is greater than zero. However, I don't know how to fulfill condition 4, i.e. how to achieve that sum of randomValues in selected rows is less than 60.
This is myTable where I'm testing the solutions:
WITH
random_values AS (
SELECT
id,
CONVERT(INT,(0.3*RAND()*number)) AS randomValue
FROM myTable
WHERE number>0
),
valid_sets AS (
SELECT
t1.id id1,
t2.id id2,
t3.id id3
FROM random_values t1
INNER JOIN random_values t2 ON (t2.id > t1.id)
INNER JOIN random_values t3 ON (t3.id > t2.id)
WHERE t1.randomValue + t2.randomValue + t3.randomValue < 60
)
SELECT c.id,c.number
FROM (SELECT TOP 1 * FROM valid_sets ORDER BY NEWID()) a
UNPIVOT(id FOR n IN (id1,id2,id3)) b
INNER JOIN myTable c ON (b.id = c.id)

Multiple count based on dynamic criteria

I have two database for which I want to compare the amount of times a case appears.
TAB1:
ID Sequence
A2D 1
A2D 2
A2D 3
A3D 1
TAB2:
ID Sequence
A2D 1
A2D 2
A3D 1
A3D 2
Now, for this example, I am trying to get this result:
ID Table1 Table2
A2D 3 2
A3D 1 2
I have tried these code without any success:
SELECT R1.ID as ID, COUNT(R1.ID) as Table1,
COUNT(R2.ID) as Table2
FROM TAB1 AS R1, TAB2 AS R2
WHERE R1.ID = R2.ID
GROUP BY R1.ID
This one gave me wrong count values...
Also, this one simply crash:
select
(
select count(*) as Table1
from TAB1
where ID = R1.ID
),(
select count(*) as Table2
from TAB2
where ID= R1.ID
)
FROM TAB1 AS R1
As you can see though, I am trying to have my criteria dynamic. Most examples I found were including basic hard-coded criteria. But for my case, I want the query to look at my first table ID, count the amount of time it appears, do it for the 2nd table with the same ID, then move on to the next ID.
If my question lacks information or is confusing just ask me, I'll do my best to be more precise.
Thanks in advance !
Here I am using a UNION ALL as a subquery
SELECT ID, SUM(T1) AS Table1, SUM(T2) AS Table2
FROM
(SELECT ID, COUNT(ID) AS T1, 0 AS T2 FROM TAB1 GROUP BY ID
UNION ALL
SELECT ID, 0 AS T1, COUNT(ID) AS T2 FROM TAB2 GROUP BY ID)
GROUP BY ID
HAVING SUM(T1)>0 AND SUM(T2)>0
I used a different approach, but unfortunately I have to use two queries, i still don't know if they can be combined together. The first one is just for making sums of both tables, and combining the results:
SELECT "Tab1" AS [Table], Tab1.ID, Count(*) AS Total
FROM Tab1
GROUP BY "Tab1", Tab1.ID
UNION SELECT "Tab2" AS [Table], Tab2.ID, Count(*) AS Total
FROM Tab2
GROUP BY "Tab2", Tab2.ID
and, since Access supports Pivot queries, you can use this:
TRANSFORM Sum(qrySums.[Total]) AS Total
SELECT qrySums.[ID]
FROM qrySums
GROUP BY qrySums.[ID]
PIVOT qrySums.[Table];
Not sure if I understand your question, but you could try something like this:
SELECT DISTINCT t.ID,
(SELECT COUNT(ID) FROM R1 WHERE ID = t.ID) AS table1,
(SELECT COUNT(ID) FROM R2 WHERE ID = t.ID) AS table2
FROM table1 t
To get the desired results, I broke it down into two sub-queries (R1SQ and R2SQ) and a main UNION query - R1R2 that uses inner, left and right joins to include all row entries including those rows that do not appear in both tables:
R1SQ
SELECT R1.Builder, Count(R1.Builder) AS Table1
FROM R1
GROUP BY R1.Builder;
R2SQ
SELECT R2.Builder_E, Count(R2.Builder_E) AS Table2
FROM R2
GROUP BY R2.Builder_E;
R1R2
SELECT R1SQ.Builder, R1SQ.Table1, R2SQ.Table2
FROM R1SQ INNER JOIN R2SQ ON R1SQ.Builder = R2SQ.Builder_E
UNION
SELECT R1SQ.Builder, R1SQ.Table1, 0 AS Table2
FROM R1SQ LEFT JOIN R2SQ ON R1SQ.Builder = R2SQ.Builder_E
WHERE (((R2SQ.Builder_E) Is Null))
UNION
SELECT R2SQ.Builder_E, 0 AS Table1, R2SQ.Table2
FROM R1SQ RIGHT JOIN R2SQ ON R1SQ.Builder = R2SQ.Builder_E
WHERE (((R1SQ.Builder) Is Null))
ORDER BY R1SQ.Builder;