Here is that query (MySQL syntax):
select
id_image
from
(
select
id_image
, count(id_image) as nb
from
data
group by
id_image
) temp_table
where
nb = (select count(distinct id_group) from data)
data is a table of 3 columns: int id_user, int id_group and int id_image
A row (x, y, z) means that:
image z is in image group y
group y was created by user x
And we want to list all the images that are present in each image group. Thanks.
You are selecting all Image IDs that occur in data as often as there are distinct group IDs in that table? That seems strange.
Anyhow, the query can be re-written as:
select id_image
from data
group by id_image
having count(*) = (select count(distinct id_group) from data);
How about try this:
select id_group, id_image from data where id_group in (select distinct id_group from data);
Related
I have a table with following structure
Table name: matches
That basically stores which product is matching which product. I need to process this table
And store in a groups table like below.
Table Name: groups
group_ID stores the MIN Product_ID of the Product_IDS that form a group. To give an example let's say
If A is matching B and B is Matching C then three rows should go to group table in format (A, A), (A, B), (A, C)
I have tried looking into co-related subqueries and CTE, but not getting this to implement.
I need to do this all in SQL.
Thanks for the help .
Try this:
;WITH CTE
AS
(
SELECT DISTINCT
M1.Product_ID Group_ID,
M1.Product_ID
FROM matches M1
LEFT JOIN matches M2
ON M1.Product_Id = M2.matching_Product_Id
WHERE M2.matching_Product_Id IS NULL
UNION ALL
SELECT
C.Group_ID,
M.matching_Product_Id
FROM CTE C
JOIN matches M
ON C.Product_ID = M.Product_ID
)
SELECT * FROM CTE ORDER BY Group_ID
You can use OPTION(MAXRECURSION n) to control recursion depth.
SQL FIDDLE DEMO
Something like this (not tested)
with match_groups as (
select product_id,
matching_product_id,
product_id as group_id
from matches
where product_id not in (select matching_product_id from matches)
union all
select m.product_id, m.matching_product_id, p.group_id
from matches m
join match_groups p on m.product_id = p.matching_product_id
)
select group_id, product_id
from match_groups
order by group_id;
Sample of the Recursive Level:
DECLARE #VALUE_CODE AS VARCHAR(5);
--SET #VALUE_CODE = 'A' -- Specify a level
WITH ViewValue AS
(
SELECT ValueCode
, ValueDesc
, PrecedingValueCode
FROM ValuesTable
WHERE PrecedingValueCode IS NULL
UNION ALL
SELECT A.ValueCode
, A.ValueDesc
, A.PrecedingValueCode
FROM ValuesTable A
INNER JOIN ViewValue V ON
V.ValueCode = A.PrecedingValueCode
)
SELECT ValueCode, ValueDesc, PrecedingValueCode
FROM ViewValue
--WHERE PrecedingValueCode = #VALUE_CODE -- Specific level
--WHERE PrecedingValueCode IS NULL -- Root
I am trying this query:
SELECT * FROM heath_check where cid = '1' and eid in('3','5','7','1','6')
My table structure:
I want distinct eid but all other data as it is. For example I have two entries with an eid of 1 my query fetched both, but I want one which is in the second column.
SELECT *
FROM heath_check AS hc
INNER JOIN (
SELECT MAX(id) AS lastId
FROM heath_check
WHERE cid = '1' and eid in('3','5','7','1','6')
GROUP BY eid) AS lastIDs
ON hc.id = lastIDs.lastId
;
You need a subquery, like the above, to find the records you want for each value. If you had wanted the first ones, you could use MIN(id) instead; if you cannot count on sequential ids, it becomes much more complex with use of potentially non-unique timestamps (if they are even available).
Create a RowNumber grouped by eid and filter the RowNumber = 1 to get the expected result.
SELECT id, eid, cid,weight, s_blood_pressure
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY eid ORDER BY id DESC) AS RowNumber
FROM heath_check
WHERE cid = '1' AND eid IN ('3','5','7','1','6')
) A
WHERE RowNumber = 1
I use mysql. My table look like this:
Last I try to use this query
SELECT * FROM movie GROUP BY `group` HAVING cateogry = 'TV'
I want with this query result as: show all but only GROUP BY TV category, where category = 'TV'
I want this Result
But my query give me this result (HAVING in query work as WHERE clouse)
IF I use this QUERY
SELECT * FROM movie GROUP BY `group`
It give me this result
I want -> QUERY -> GROUP BY group (ID no 9 and ID 1,2,3 treat as different group name)
IF group has all same values BUT category='movie' (RETURN ALL ROWS
group by NOT APPLY)
IF group has all same values BUT category='TV' (RETURN 1 ROW group by APPLY)
You seem to want this query:
select m.*
from movie m join
(select `group`, min(id) as minid
from movie
group by `group`
) g
on m.id = g.minid;
SELECT min(ID) as ID, min(Name), `group`, Category
FROM movie
GROUP BY `group`, Category
ORDER BY ID
Have you tried the below? I think you are pretty close. As when you are grouping your 'group' t. You are also grouping the one whose category is movie as well. So you just need to create a separate group Category.
SELECT * FROM movie
WHERE group = 't'
GROUP BY group, Category
ORDER BY ID
I have a MySQL table where I have a certain id as a foreign key coming from another table. This id is not unique to this table so I can have many records holding the same id.
I need to find out which ids are seen the least amount of times in this table and pull up a list containing them.
For example, if I have 5 records with id=1, 3 records with id=2 and 3 records with id=3, I want to pull up only ids 2 & 3. However, the data in the table changes quite often so I don't know what that minimum value is going to be at any given moment. The task is quite trivial if I use two queries but I'm trying to do it with just one. Here's what I have:
SELECT id
FROM table
GROUP BY id
HAVING COUNT(*) = MIN(SELECT COUNT(*) FROM table GROUP BY id)
If I substitute COUNT(*) = 3, then the results come up but using the query above gives me an error that MIN is not used properly. Any tips?
I would try with:
SELECT id
FROM table
GROUP BY id
HAVING COUNT(*) = (SELECT COUNT(*) FROM table GROUP BY id ORDER BY COUNT(*) LIMIT 1);
This gets the minimum selecting the first row from the set of counts in ascendent order.
You need a double select in the having clause:
SELECT id
FROM table
GROUP BY id
HAVING COUNT(*) = (SELECT MIN(cnt) FROM (SELECT COUNT(*) as cnt FROM table GROUP BY id) t);
The MIN() aggregate function is suposed to take a column, not a query. So, I see two ways to solve this:
To properly write the subquery, or
To use temp variables
First alternative:
select id
from yourTable
group by id
having count(id) = (
select min(c) from (
select count(*) as c from yourTable group by id
) as a
)
Second alternative:
set #minCount = (
select min(c) from (
select count(*) as c from yourTable group by id
) as a
);
select id
from yourTable
group by id
having count(*) = #minCount;
You need to GROUP BY to produce a set of grouped values and additional select to get the MIN value from that group, only then you can match it against having
SELECT * FROM table GROUP BY id
HAVING COUNT(*) =
(SELECT MIN(X.CNT) AS M FROM(SELECT COUNT(*) CNT FROM table GROUP BY id) AS X)
I have a table called data:
create table data
(
ID int primary key,
val varchar(50),
forID int
constraint fk_forID foreign key (forID) references otherTable(forID)
)
I have a view called dataFrequencies
create view dataFrequencies (val, freq)
as select val, COUNT(*)
from data
group by val
order by freq desc
What I want is the subset of rows from table data where val is in the top fifty rows of dataFrequencies.
My current solution is somewhat roundabout. I create a table topFifty that contains the top 50 rows of dataFrequencies. Then I create a view topFiftyVals which selects all from data but inner joins on table topFifty:
create table topFifty
(
val varchar(50) primary key
)
insert into topFifty select val from dataFrequencies order by frequency desc limit 50;
create view topFiftyVals (ID, val, forID)
as select *
from data d
inner join topFifty tf on d.val = tf.val
I am sure there is some kind of direct querying method that will do this! Thanks for all the help!
Yes, there is a direct way. It's the code in your topFiftyVals view, slightly altered:
select d.*, tf.freq
from data d
inner join ( select val, COUNT(*) AS freq
from data
group by val
order by freq desc
limit 50
) tf
on d.val = tf.val ;
Couldn't you just do:
SELECT *
FROM data
WHERE val IN (SELECT val
FROM dataFrequencies
ORDER BY frequency DESC
LIMIT 50);