mysql> select * from productdetails;
+----------+---------+--------+
| customer | product | is_use |
+----------+---------+--------+
| 1 | 1 | 0 |
| 1 | 2 | 0 |
| 1 | 3 | 1 |
| 2 | 1 | 1 |
| 2 | 2 | 0 |
| 2 | 3 | 1 |
| 3 | 1 | 1 |
| 3 | 2 | 1 |
| 3 | 3 | 1 |
| 4 | 1 | 0 |
| 4 | 2 | 1 |
| 4 | 3 | 1 |
+----------+---------+--------+
12 rows in set (0.00 sec)
How to get the customers for using both product 1 and 2 from the above table
In order to know which customers use both products, you'd aggreagte per customer:
select customer
from productdetails
group by customer
having sum(product = 1 and is_use = 1) > 0
and sum(product = 2 and is_use = 1) > 0
;
Solutions using IN(1,2) will find customers who use either product 1 or product 2 (or both).
If you want to find customers who use both product 1 and product 2, you need to test for both simultaneously.
But a WHERE clause naturally applies conditions in the context of only one row at a time.
So you need to get two rows onto one row somehow.
The best way to do this is with a self-join:
SELECT p1.customer
FROM product_detail AS p1
JOIN product_detail AS p2 ON p1.customer = p2.customer
WHERE p1.product = 1 AND p1.is_use = 1
AND p2.product = 2 AND p2.is_use = 1
You can use IN clause:
SELECT customer
FROM product_detail
WHERE product IN (1, 2)
AND is_use = 1;
Related
I am not able to figure out how I can get the following result with one MySQL Query:
I have two tables:
shop_items
| id | description | price | active |
+----+-------------+-------+--------+
| 1 | product_1 | 5 | 1 |
+----+-------------+-------+--------+
| 2 | product_2 | 10 | 1 |
+----+-------------+-------+--------+
| 3 | product_3 | 15 | 0 |
+----+-------------+-------+--------+
inventory_items (the shop_items a user purchased)
| id | item_id | user_id | active |
+----+---------+---------+--------+
| 1 | 2 | 1 | 1 |
+----+---------+---------+--------+
| 2 | 1 | 1 | 0 |
+----+---------+---------+--------+
I want to see all shop_items where active = 1 including a row called purchased = 0 or 1 based on inventory_items -> matching user_id (where user_id = something) and active = 1
Example output based on the data from above tables -> where user_id = 1:
| item_id | price | description | purchased |
+---------+-------+-------------+-----------+
| 1 | 5 | product_1 | 0 |
+---------+-------+-------------+-----------+
| 2 | 10 | product_2 | 1 |
+---------+-------+-------------+-----------+
What query do I need for this output?
Please note: I only need the result from ONE user_id which I can change within the query :)
Test
SELECT shop_items.*, COALESCE(inventory_items.active, 0) purchased
FROM shop_items
LEFT JOIN inventory_items ON shop_items.id = inventory_items.item_id
AND user_id = 1
WHERE shop_items.active = 1
I need to count shutouts for goalies. I have two tables ("players" and "gamestats"). I have a problem getting the values when goalie has no "0" / zero values in "goalsagainst" column when the goalie is "dressed" (has games).
So, I need to count all the zero values from column "goalsagainst" when "dressed" column has a value 1 as a "shutout" column. And if values from column "goalsagains" are more than 0 "shutout" colmn values should be 0;
I have tried the other solutions from similar topics, but I always have the same outcome where only the zero values are counted and other values are not shown.
My structure:
players
|p_id|pos|
--------
| 1 | G |
--------
| 2 | D |
--------
| 3 | O |
--------
| 4 | G |
stats
|g_id|p_id|goalsagainst|dressed|
--------------------------------
| 1 | 1 | 2 | 1 |
--------------------------------
| 1 | 4 | 0 | 0 |
--------------------------------
| 1 | 3 | NULL | 1 |
--------------------------------
| 1 | 2 | NULL | 1 |
--------------------------------
| 2 | 1 | 0 | 0 |
--------------------------------
| 2 | 4 | 0 | 1 |
--------------------------------
| 2 | 3 | NULL | 1 |
--------------------------------
| 2 | 2 | NULL | 1 |
SELECT
stats.id,
COUNT(stats.goalsagainst) AS shutouts
FROM `stats`
RIGHT JOIN players
ON stats.id = players.id
WHERE goalsagainst = 0
AND players.pos = 'G'
AND stats.dressed = 1
GROUP BY stats.id;
my result is:
p_id|shutouts
-------------
4 | 1
when it should be:
p_id|shutouts
-------------
1 | 0
-------------
4 | 1
Your problem is that your conditions on the stats table in your WHERE clause effectively turn the RIGHT JOIN into an INNER JOIN. To work around this, move the conditions to the ON clause. Secondly, you need to use players.p_id in the SELECT and GROUP BY as stats.p_id may be NULL:
SELECT players.p_id,
COUNT(stats.goalsagainst) AS shutouts
FROM `stats`
RIGHT JOIN players ON stats.p_id = players.p_id AND stats.dressed = 1 AND stats.goalsagainst = 0
WHERE players.pos = 'G'
GROUP BY players.p_id;
Output:
p_id shutouts
1 0
4 1
Demo on dbfiddle
I have the following data in my database:
scu_banks:
---------------------------------
| id | type | name |
|-------------------------------|
| 1 | 1 | One |
| 2 | 1 | Two |
| 3 | 2 | Three |
| 4 | 3 | Four |
---------------------------------
scu_statement:
---------------------------------
| id | code | status |
|-----------------------------------|
| 1 | 1 | 0 |
| 2 | 1 | 1 |
| 3 | 2 | 0 |
| 4 | 1 | 0 |
-------------------------------------
What I want to do is I want to select all the rows in table scu_banks and calculate how many rows I have with the status 0. The data should be represented like:
--------------------------------------------------------------
| scu_banks.type | scu_banks.name | status | scu_banks.id |
--------------------------------------------------------------
| 1 | One | 2 | 1 |
| 1 | Two | 0 | 2 | //There is no row with status 0
| 2 | Three | 0 | 3 |
| 3 | Four | 0 | 4 |
--------------------------------------------------------------
When I run my sql statement I get the following data:
---------------------------------------------------------------
| scu_banks.type | scu_banks.name | status | scu_banks.id |
--------------------------------------------------------------
| 1 | One | 2 | 1 |
---------------------------------------------------------------
The data I get in this case is correct. 2 it the total count of all the rows in table scu_statement. The statement also dont shows the other rows in the database.
Does someone know what is wrong with my sql statement?
Here is my sql statement:
SELECT b.type 'scu_banks.type',
b.name 'scu_banks.name',
count(y.status) 'status',
b.id 'scu_banks.id'
FROM scu_banks b
LEFT JOIN (SELECT s.code, count(s.status) status
FROM scu_bankstatement s
WHERE status='0'
GROUP BY s.code) y
ON y.code = b.id
You need a GROUP BY in your outer query, otherwise the query simply counts status for all banks. You can also simplify your query by just LEFT JOINing the two tables on code/id and status = 0
SELECT b.type `scu_banks.type`,
b.name `scu_banks.name`,
COUNT(s.status) `status`,
b.id `scu_banks.id`
FROM scu_banks b
LEFT JOIN scu_statement s ON s.code = b.id AND s.status = 0
GROUP BY b.id, b.name, b.type
Output
scu_banks.type scu_banks.name status scu_banks.id
1 One 2 1
1 Two 1 2
2 Three 0 3
3 Four 0 4
Demo on dbfiddle
How to select rows which are not defined? Like row 2 have undefined day 3 and row 3 have undefined day 1. I want them to be 0 in result set.
+----+-----+-------+
| id | day | count |
+----+-----+-------+
| 1 | 1 | 262 |
| 1 | 2 | 685 |
| 1 | 3 | 984 |
| 2 | 1 | 692 |
| 2 | 2 | 962 |
| 3 | 2 | 355 |
| 3 | 3 | 741 |
+----+-----+-------+
EDIT:
I want select count from days 1, 2 and 3 (not whole table) and display 0 on undefined day.
We can get all unique id values in a Derived Table.
For day, you seem to want only 1,2 and 3 only. So we can directly consider these values only using UNION ALL.
CROSS JOIN between them to get all possible combinations.
LEFT JOIN from all_combinations table to the main table on id and day.
We can use Coalesce() function to consider 0 value for count, for the cases where there is no matching row in the main table
Try the following:
SELECT all_combinations.id,
all_combinations.day,
COALESCE(t.count, 0) AS count
FROM
(
SELECT ids.id, days.day
FROM
(SELECT DISTINCT id FROM your_table) AS ids
CROSS JOIN
(SELECT 1 AS day UNION ALL SELECT 2 UNION ALL SELECT 3) AS days
) AS all_combinations
LEFT JOIN your_table AS t
ON t.id = all_combinations.id AND
t.day = all_combinations.day
Result:
| id | day | count |
| --- | --- | ----- |
| 1 | 1 | 262 |
| 2 | 1 | 692 |
| 3 | 1 | 0 |
| 1 | 2 | 685 |
| 2 | 2 | 962 |
| 3 | 2 | 355 |
| 1 | 3 | 984 |
| 2 | 3 | 0 |
| 3 | 3 | 741 |
View on DB Fiddle
I have a source table (piece of it):
+--------------------+
| E M P L O Y E E |
+--------------------+
| ID | EQUIPMENT |
+--------------------+
| 1 | tv,car,phone |
| 2 | car,phone |
| 3 | tv,phone |
+----+---------------+
After normalization process I ended with two new tables:
+----------------+
| DICT_EQUIPMENT |
+----------------+
| ID | EQUIPMENT |
+----------------+
| 1 | tv |
| 2 | car |
| 3 | phone |
+----+-----------+
+---------------------+
| SET_EQUIPMENT |
+----+--------+-------+
| ID | SET_ID | EQ_ID |
+----+--------+-------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 1 | 3 |
| 4 | 2 | 2 |
| 5 | 2 | 3 |
| 6 | 3 | 1 |
| 7 | 3 | 3 |
+----+--------+-------+
(the piece/part)
+-----------------+
| E M P L O Y E E |
+-----------------+
| ID | EQ_SET_ID |
+-----------------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
+----+------------+
And now when I want to find correct SET_ID I can write something like this:
SELECT SET_ID
FROM SET_EQUIPMENT S1,
SET_EQUIPMENT S2,
SET_EQUIPMENT S3
WHERE S1.SET_ID = S2.SET_ID
AND S2.SET_ID = S3.SET_ID
AND S1.EQ_ID = 1
AND S2.EQ_ID = 2
AND S3.EQ_ID = 3;
Maybe any ideas for optimize this query? how find the correct set?
First, you should use explicit join syntax for the method you are using:
SELECT S1.SET_ID
FROM SET_EQUIPMENT S1 JOIN
SET_EQUIPMENT S2
ON S1.SET_ID = S2.SET_ID JOIN
SET_EQUIPMENT S3
ON S2.SET_ID = S3.SET_ID
WHERE S1.EQ_ID = 1 AND
S2.EQ_ID = 2 AND
S3.EQ_ID = 3;
Commas in a from clause are quite outdated. (And, this fixes a syntax error in your query.)
An alternative method is to use group by with a having clause:
SELECT S.SET_ID
FROM SET_EQUIPMENT S
GROUP BY S.SET_ID
HAVING SUM(CASE WHEN S.EQ_ID = 1 THEN 1 ELSE 0 END) > 0 AND
SUM(CASE WHEN S.EQ_ID = 2 THEN 1 ELSE 0 END) > 0 AND
SUM(CASE WHEN S.EQ_ID = 3 THEN 1 ELSE 0 END) > 0;
Which method works better depends on a number of factors -- for instance, the database engine you are using, the size of the tables, the indexes on the tables. You have to test which method works better on your system.
You've normalised wrongly. Get rid of set_equipment
Change to have three tables: employee, equipment, employee_equipment.
If you're looking for the equipment for a given employee you want to use:
select id, equipment
from equipment eq
inner join employee_equipment ee on eq.id = ee.eq_id
inner join employee emp on emp.id = ee.emp_id
where emp.id = 2