This question already has answers here:
MYSQL Select from tables based on multiple rows
(3 answers)
Closed 6 years ago.
If I have a table similar to the following:
+-------------+------------+-----------------+
| instance_id | product_id | option_value_id |
+-------------+------------+-----------------+
| 1 | 1 | 1 |
| 1 | 1 | 2 |
| 1 | 1 | 3 |
| 2 | 1 | 1 |
| 2 | 1 | 3 |
| 2 | 1 | 4 |
+-------------+------------+-----------------+
How would I create a query to find that instance_id 2 represents an instance of product_id 1 that has option values 1,3 and 4?
For example, I'd like to be able to query the table something like as follows:
select instance_id from instances where product_id = 1 'having' option_value_id = 1 and option_value_id=3 and option_value_id=4 (obviously this won't actaully work) and get the result
+-------------+
| instance_id |
+-------------+
| 1 |
Any help or pointers much appreciated
select product_id
, group_concat(option_value_id)
from table
where instance_id = 1
group by instance_id;
Obviously won't get what you want if product_id changes within instance_id, i.e. you could have multiple product_ids per instance_id. I don't know the schema but the above should get you started.
would help to know what your desired output would be... but perhaps something like:
Select A.Instannce_ID, B.instance_ID, group_concat(Distinct option_value_ID SEPERATOR ',') as Option_Values
from Table A
INNER JOIn table B
on A.Product_ID = B.Product_ID
and A.Instance_ID < B.Instance_ID
WHERE Option_value_ID In (1,3,4)
GROUP BY A.Instannce_ID, B.instance_ID
HAVING Count(distinct option_value_ID) = 3
This does a self join on the product_ID ensuring that the instances don't match and we don't get two way matches, and reports the option values in 1 field.
Related
This question already has answers here:
How can I return pivot table output in MySQL?
(10 answers)
Closed 5 years ago.
sorry for the weird question but I didn't know how to exactly ask this. Or if there are similar questions to look at, please let me know.
I have the following table in my database. Basically it stores the prices of an item at different stores. Every store will always have the same items, meaning if store_id 3, 4,... n values are later added, they will have the same item_ids
+----+---------+----------+---------+
| id | item_id | store_id | price |
+----+---------+----------+---------+
| 1 | 1 | 1 | 74.99|
| 2 | 2 | 1 | 25.99|
| 3 | 3 | 1 | 89.99|
| 4 | 1 | 2 | 69.99|
| 5 | 2 | 2 | 39.99|
| 6 | 3 | 2 | 95.99|
+----+---------+----------+---------+
My sql knowledge is pretty basic, but I was wondering if there is a way to get this result.
I need to add every store_id value as a column and then get the price value for the item_id at every store available and put that in a single row. Since there could be more values for store_id, every different value
+---------+-----------+-----------+
| item_id | price for | price for |
| | store_id 1| store_id 2|
+---------+-----------+-----------+
| 1 | 74.99 | 69.99|
| 2 | 25.99 | 39.99|
| 3 | 89.99 | 95.99|
+---------+-----------+-----------+
Thanks.
you could use a self join eg:
select a.item_id, a.price as price_store_1, b.price as price_store_2
from my_table a
inner join my_table b on a.item_id = b.item_1 and b.store_id = 2
where a.store_id = 1
I am facing a conundrum; not sure why -- is it because this late, or I am just stuck. My goal is to create a filter on the webpage, so I am trying to figure this out.
I have a list of products that I store with filters in the reference table product_filter.
The structure:
id | product_id | filter1_id | filter2_id
1 | 1 | 2 | 1 <---
2 | 1 | 4 | 3
3 | 1 | 5 | 1
4 | 2 | 2 | 1 <---
5 | 2 | 3 | 1
6 | 3 | 2 | 1 <---
7 | 3 | 3 | 4
I need to submit a list of products (for example 1,2,3) and get only those filter combinations, that are the same for all selected product id's. So the result needs to be
filter1_id | filter2_id
2 | 1
My problem is that my products might vary and I can't do a ton of self inner joins... so I am stuck... Any advise?
Here is one approach that you could try:
select filter1_id, filter2_id
from product_filter
group by filter1_id, filter2_id
having count(*)=(
select count(distinct product_id)
from product_filter
)
This will only return a list when a combination of filter1_id and filter2_id exists for every product_id. (Fiddle here.) Is that what you are after? Do you don't mention what should be returned if there isn't any combination that exists for all of the given product_id's - an empty result set?
It's not a self-join (or even a ton of them ;) ) but it will still be fairly expensive I imagine.
This is my table structure-
TABLE : T_LOG
---------------------------------------------------
| ID | AREA | USER_ID | DATE
---------------------------------------------------
| 1 | AREA1 | 5 | 2000-05-17
---------------------------------------------------
| 2 | AREA1 | 5 | 2002-12-12
---------------------------------------------------
| 3 | AREA2 | 5 | 2003-02-19
---------------------------------------------------
| 4 | AREA1 | 5 | 2006-05-22
---------------------------------------------------
| 5 | AREA2 | 5 | 2006-07-29
---------------------------------------------------
| 6 | AREA3 | 5 | 2009-05-07
---------------------------------------------------
In this table USER_ID 5 has been to several AREAs at several DATEs.
I want to pick how many (uniquely) AREAs the particular USER_ID has been to so far.
The following query
SELECT COUNT(*) FROM T_LOG WHERE USER_ID = 5 GROUP BY 'AREA'
returns 6 as in 6 entries. But I want it to return 3 as in 3 Areas uniquely (AREA1, AREA2, AREA3)
How do I correct this query?
You can use count (distinct):
SELECT COUNT(DISTINCT AREA) FROM T_LOG WHERE USER_ID = 5
Your actual problem is that you have specified Area column as a value in the GROUP BY clause (i.e. GROUP BY 'Area'). Which should be without single quotes. (i.e. GROUP BY Area)
So try this query:
SELECT COUNT(*) FROM T_LOG WHERE USER_ID = 5 GROUP BY AREA
See this SQLFiddle
Alternatively you can directly use COUNT(DISTINCT Area) as already mentioned in other answers (which one is more preferable).
SELECT COUNT(DISTINCT AREA), USER_ID FROM T_LOG WHERE USER_ID = 5
I'm trying to do something like 'select groupwise maximum', but I'm looking for groupwise order number.
so with a table like this
briefs
----------
id_brief | id_case | date
1 | 1 | 06/07/2010
2 | 1 | 04/07/2010
3 | 1 | 03/07/2010
4 | 2 | 18/05/2010
5 | 2 | 17/05/2010
6 | 2 | 19/05/2010
I want a result like this
breifs result
----------
id_brief | id_case | dateOrder
1 | 1 | 3
2 | 1 | 2
3 | 1 | 1
4 | 2 | 2
5 | 2 | 1
6 | 2 | 3
I think I want to do something like described here MySQL - Get row number on select, but I don't know how I would reset the variable for each id_case.
This will give you how many records are there with this id_case value and a date less than or equal to this date value.
SELECT t1.id_brief,
t1.id_case,
COUNT(t2.*) AS dateOrder
FROM yourtable AS t1
LEFT JOIN yourtable AS t2 ON t2.id_case = t1.id_case AND t2.date <= t1.date
GROUP BY t1.id_brief
Mysql is permissive about columns which can be queries using GROUP BY. With a more stric DBMS you may need GROUP BY t1.id_brief, t1.id_case.
I strongly advise you to have the right indexes on the table:
CREATE INDEX filter1 ON yourtabl (id_case, date)
I have following table:
+--------+-----------+--------+
| ID | Title | Stat |
+--------+-----------+--------+
| 1 | title a | 1 |
+--------+-----------+--------+
| 1 | title b | 0 |
+--------+-----------+--------+
| 2 | title c | 1 |
+--------+-----------+--------+
| 2 | title d | 1 |
+--------+-----------+--------+
| 3 | title e | 0 |
+--------+-----------+--------+
| 3 | title f | 1 |
+--------+-----------+--------+
| 3 | title g | 1 |
+--------+-----------+--------+
I need to construct a query, where as a result only those records would be included where ALL values in column Stat meet certain condition.
For above table, how to formulate a query that would basically mean: show me records for only those ID's that have all the values in column Stat = 1 and would as a result produce following table?
+--------+-----------+--------+
| 2 | title c | 1 |
+--------+-----------+--------+
| 2 | title d | 1 |
+--------+-----------+--------+
Thanks.
Something like this?
SELECT
*
FROM table t
LEFT JOIN (
SELECT
MIN(Stat) AS Stat,
ID
FROM table
GROUP BY ID
) minstat ON t.ID = minstat.ID
WHERE minstat.Stat = 1;
Basically, the subquery computes the minimum stat per ID, whereas the outer query only selects the rows with the minimal stat equal to 1. If all rows need to satisfy a certain condition, insert a boolean expression in stead of Stat in the minimum.
Not sure if this is possible without a subquery.
This also works,
SELECT * FROM tablename t1
WHERE (
SELECT COUNT(*) FROM tablename t2
WHERE t1.ID = t2.ID AND t2.STAT = 0
) = 0
this query checks, is where a STAT with value 0 in records with same ID.
How about this:
select * from t where not (id in (select id from t where stat=0));
All 3 suggested solutions above work well, difference is only in the speed of execution. On a table where 3 records are found among approximately 7000 results are:
Martijn's: Showing rows 0 - 2 (3 total, Query took 0.0069 sec)
Alex's: Showing rows 0 - 2 (3 total, Query took 0.1162 sec)
Pavelasc's: Showing rows 0 - 2 (3 total, Query took 0.6160 sec)