Mysql select row based on multiple rows in same table - mysql

I have the following table structure:
item_id | value |
==================
1 | 1 |
1 | 3 |
1 | 4 |
2 | 2 |
2 | 3 |
2 | 4 |
2 | 5 |
3 | 1 |
3 | 5 |
3 | 6 |
4 | 1 |
4 | 3 |
4 | 4 |
4 | 5 |
I have a query that returns those item_id whose value matches with 1, 3 and 4.
So here, the item_ids that should be returned are 1 and 4.
My query:
select item_id from table t
where exists (select item_id from table t1 where value = 1 and t1.item_id = t.item_id)
and exists (select item_id from table t1 where value = 2 and t1.item_id = t.item_id) group by item_id
This query is working fine. Here i am matching only 3 values. What if i want to match 50 such values from the table? (all the 50 values are stored in a php array) The query will be huge and also i want to do the same thing from two different tables in the same query. So, this will double the size of an already huge query. Please suggest me some other way around.
Edited::
table 2
--------
item_id | user_id |
==================
1 | 1 |
1 | 5 |
1 | 7 |
2 | 2 |
2 | 3 |
2 | 4 |
2 | 5 |
3 | 1 |
3 | 5 |
3 | 6 |
4 | 1 |
4 | 3 |
4 | 4 |
4 | 5 |
Now, i want item_id where values from table1 are 1,3,4 and user_id from table2 are 1,5,7

This problem is called Relational Division.
SELECT item_ID
FROM tableName
WHERE value IN (1,3,4)
GROUP BY item_ID
HAVING COUNT(*) = 3
if uniqueness was not enforce on column value for every item_id, DISTINCT is required to count only unique values,
SELECT item_ID
FROM tableName
WHERE value IN (1,3,4)
GROUP BY item_ID
HAVING COUNT(DISTINCT value) = 3
SQLFiddle Demo (both query included)
SQL of Relational Division

Related

Select count where two columns aren't equal to 0

I have a table as below mentioned:
|----------------|-------------|-------------|
| a_id | m_id | e_id |
|----------------|-------------|-------------|
| 1 | 1 | 0 |
| 2 | 2 | 2 |
| 3 | 3 | 3 |
| 4 | 1 | 1 |
| 5 | 4 | 4 |
|----------------|-------------|-------------|
I need a query that performs the task that a_id should have either m_id or e_id not equal to 0.
So, I wrote the query as follows which returns count 5:
SELECT count(a_id) from ids where (e_id!=0 or m_id!=0)
I need a_id should have distinct m_id != 0. That should return count 4.
use count(distinct
select count(distinct m_id) from ids where e_id!=0 or m_id!=0

Copy value from one row to all rows having the same groupID

Here's my MySQL table:
ID | groupID | value
------------------------------
1 | 1 |
2 | 1 | 0.34353
3 | 1 |
4 | 2 |
5 | 2 | 0.23232
6 | 3 |
7 | 3 |
8 | 3 | 1.23234
9 | 3 |
I want to copy the available values from each group to ALL rows with the same groupID, so that my final table will look like this:
ID | groupID | value
------------------------------
1 | 1 | 0.34353
2 | 1 | 0.34353
3 | 1 | 0.34353
4 | 2 | 0.23232
5 | 2 | 0.23232
6 | 3 | 1.23234
7 | 3 | 1.23234
8 | 3 | 1.23234
9 | 3 | 1.23234
There is no fixed amount of how many rows one group has. How can I do this?
You can accomplish this using an update join. Join your initial table to a subquery which identifies the non NULL value for each groupID. After bringing in that information, update non NULL value columns to the value from the subquery.
UPDATE yourTable t1
INNER JOIN
(
SELECT groupID, MAX(value) AS value
FROM yourTable
GROUP BY groupID
) t2
ON t1.groupID = t2.groupID
SET t1.value = t2.value
WHERE COALESCE(t1.value, '') = ''
Update:
It appears that you may have empty string for the missing data, and/or NULL in addition to that. In this case, MAX() should still pickup on the non missing data, but I changed the WHERE clause appropriately.

MySQL - select results from a secondary table as a column in a primary table

I have a set of data consisting of two tables: table one is a set of unique items, and table two is a log of references that link the items in the first table together. For example:
Table one
+------------+--------------------+
| id | name |
+------------+--------------------+
| 1 | Item 1 |
| 2 | Item 2 |
| 3 | Item 3 |
| 4 | Item 4 |
| 5 | Item 5 |
+------------+--------------------+
Table two
+------------+--------------------+
| item_1_id | item_2_id |
+------------+--------------------+
| 1 | 2 |
| 1 | 3 |
| 1 | 5 |
| 2 | 4 |
| 2 | 5 |
+------------+--------------------+
Is it possible to group the rows that are in table two, and display them in some sort of array/collection as a column in table one. So based on my example tables, I would hope to return something like this:
+------------+-----------+----------+
| id | name | results |
+------------+-----------+----------+
| 1 | Item 1 | 2, 3, 5 |
| 2 | Item 2 | 1, 4, 5 |
| 3 | Item 3 | 1 |
| 4 | Item 4 | 2 |
| 5 | Item 5 | 1, 2 |
+------------+-----------+----------+
You can use group_concat for show the aggregated result and a select union for obtain both the related item for grouping
select id, name, group_concat( item1)
from table_one
left join
(select item_1_id as item1, item_2_id as item2
from table_two
union
select item_2_id , item_1_id
from table_two
order by item1) t1 ont1.item1 = table_one.id
group by id, name

Group by two values

I have the following query:
SELECT
items.*
FROM
`items`
INNER JOIN
`users` ON `items`.`owner` = `users`.`id`
GROUP BY
`items`.`owner`
LIMIT
10
I ensures it is grouped by the user (only one item fetched per user), but I also wish ensure that items with the category, say, "1" only appears once.
But that does not work. Well, query succeeds, but it does not group by category. Multiple categories is still shown. Any ideas?
I have created a SQLFiddle here: http://sqlfiddle.com/#!2/0a4bad/1
Instead of outputting:
+----+----------+-------+
| ID | CATEGORY | OWNER |
+----+----------+-------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 1 | 3 |
| 4 | 2 | 4 |
| 5 | 2 | 5 |
+----+----------+-------+
It should be outputting:
+----+----------+-------+
| ID | CATEGORY | OWNER |
+----+----------+-------+
| 1 | 1 | 1 |
| 4 | 2 | 2 |
| 5 | 2 | 4 |
| 5 | 2 | 5 |
| 8 | 3 | 3 |
+----+----------+-------+
(notice category 1 is only shown ONCE).
I want to ensure that only one item per owner is shown, and then adtionally ensure that a specific category (say 1 and 5) is only shown once. The category 1 and 5 are overpopulated, and if they are not limited, they will be 90% of the output.
You can use DISTINCT to retrieve unique data:
SELECT DISTINCT items.category
select * from items t1
where category not in (1,2)
or not exists (
select 1 from items t2
where t2.id < t1.id
and t2.category = t1.category
)
group by owner
http://sqlfiddle.com/#!2/0a4bad/27

add record for every single id when join table

I need help with query
let say i have 2 tables
tableA
------------------------------------------
id | name
1 | ABC
2 | DEF
3 | GHI
tableB
------------------------------------------
id | anotherID | Amount
1 | 1 | 1000
2 | 1 | 2000
3 | 1 | 3000
1 | 2 | 4000
2 | 2 | 5000
1 | 3 | 6000
i need this list
jointable
------------------------------------------
id | anotherID | Amount
1 | 1 | 1000
2 | 1 | 2000
3 | 1 | 3000
1 | 2 | 4000
2 | 2 | 5000
3 | 2 | 0
1 | 3 | 6000
2 | 3 | 0
3 | 3 | 0
i need every single id have value even its 0 for every single anotherID value..
example :
tableA have 3 id & distinct anotherID tableB have 3 records so i will need 3 * 3 = 9 records..
how to do this with query?? i can do with left join and union but i want to know if there some more effective way to do it.
SQLFiddle demo
select T1.ID,T2.AnotherId,
COALESCE(T3.Amount,0) as Amount
FROM TableA as T1
CROSS JOIN (Select distinct anotherID FROM TableB) as T2
LEFT JOIN TableB as T3 on (T1.id=T3.id)
AND
(T2.anotherID=T3.anotherID)
Order by T2.anotherId,T1.Id