Hi im having 2 tables customers and customer_items.
There is now a customer_id in both tables in the 2nd table each customer can have multiple items so the table can be like this
id | item
----------------------------
1501 | pillow
1501 | blanket
1501 | others
1502 | pillow
1502 | blanket
1502 | others
now how can i select with a mysql query the customers that have both pillow and blanket
This is my last approach
select custlist.id FROM customers custlist LEFT JOIN customer_items custitems ON custitems.id=custlist.id WHERE (custitems.items='pillow' AND custitems.items='blanket') UNION ALL
This is a Relational Division problem.
SELECT a.customer_ID
FROM customers a
INNER JOIN customer_items b
ON a.customer_ID = b.customer_ID
WHERE b.item IN ('pillow', 'blanket')
GROUP BY a.customer_ID
HAVING COUNT(*) = 2
SQL of Relational Division
If item is not unique for every customer_ID, a DISTINCT keyword is need to count only unique records.
SELECT a.customer_ID
FROM customers a
INNER JOIN customer_items b
ON a.customer_ID = b.customer_ID
WHERE b.item IN ('pillow', 'blanket')
GROUP BY a.customer_ID
HAVING COUNT(DISTINCT b.item) = 2
Slight variation of the above solution by JW:-
SELECT a.customer_ID
FROM customers a
INNER JOIN (SELECT customer_ID, item FROM customer_items WHERE item = 'pillow' GROUP BY customer_ID) PillowCheck
ON a.customer_ID = PillowCheck.customer_ID
INNER JOIN (SELECT customer_ID, item FROM customer_items WHERE item = 'blanket' GROUP BY customer_ID) BlanketCheck
ON a.customer_ID = PillowCheck.customer_ID
Try this query
SELECT
a.id
FROM
customer_items a
INNER JOIN
customer_items b
ON
a.id= b.id and
a.item = 'PILLOW' AND
b.item='blanket'
if you want customer name then just join customer table. If customer have multiple pillow or blanket then add distinct
SELECT
distinct customer_ID ,item
FROM
customer_items
WHERE item in ('PILLOW', 'blanket')
GROUP BY customer_ID
HAVING COUNT(item) = 2
Related
I have organizations. Each organization can have members and projects.
I want to get list of organizations with number of members and projects.
For example,
Organization | Members | Projects | Action
------------------------------------------
Org 1 | 5 | 6 | Delete - Edit
Org 2 | 2 | 9 | Delete - Edit
I am using this query,
SELECT COUNT(m.id) as members, COUNT(p.id) as projects,
o.status,o.organization_name,o.logo, o.id as id
from tbl_organizations o
LEFT JOIN tbl_organization_members m ON (o.id = m.organization_id)
LEFT JOIN tbl_projects p ON (o.id = p.organization_id)
WHERE o.status= 'active' AND o.created_by= 1
But the output of number of projects is equal to number of members.
How can I make the sample above using query?
Try this way:
SELECT o.id as id, o.organization_name, cnt_ as members, cnt_p as projects
from tbl_organizations o
LEFT JOIN (
SELECT organization_id, COUNT(id) cnt_m
FROM tbl_organization_members
GROUP BY organization_id
) m ON (o.id = m.organization_id)
LEFT JOIN (
SELECT organization_id, COUNT(id) cnt_p
FROM tbl_projects
GROUP BY organization_id
) p ON (o.id = p.organization_id)
WHERE o.status= 'active' AND o.created_by= 1
This way you JOIN to an already aggregated version of member/project tables, so as to get the count of members/projects per organization_id.
Group by the organisation columns and count distinct IDs
SELECT o.status,o.organization_name, o.logo, o.id as id,
COUNT(distinct m.id) as members, COUNT(distinct p.id) as projects,
from tbl_organizations o
LEFT JOIN tbl_organization_members m ON (o.id = m.organization_id)
LEFT JOIN tbl_projects p ON (o.id = p.organization_id)
WHERE o.status= 'active'
AND o.created_by= 1
GROUP BY o.status, o.organization_name, o.logo, o.id
You can co-related subquery:
SELECT
o.id as Organization,
(SELECT COUNT(*) FROM tbl_organization_members WHERE organization_id = o.id) as members,
(SELECT COUNT(*) FROM tbl_projects WHERE organization_id = o.id) as projects
FROM
tbl_organizations o
WHERE
o.status= 'active' AND o.created_by = 1
I have two table 1 is account and the other one is account_spend_history AS ash account is the parent/master table and the shin a sub table. and has a relationship OneToMany with account(account table id is a foreign key in ash as account_id). please see the image
Now I need to get the account.id, total spend (which is the sum of the amount_spend with same account_id) and last spend (is the last record inserted in ash table against and account_id i.e. amount_spend value corresponding with MAX(ash.id)), that is
id | spend_total | last_spend
---------------------------------
1 | 30 | 18
2 | 280 | 120
3 | 20 | 20
SELECT a.id, SUM(ash.amount_spend) AS spend_total
FROM accounts as a
INNER JOIN account_spend_history AS ash ON ash.account_id = a.id
GROUP BY a.id
Im getting the account.id and sum of ash.amount spend, but I also need last spend. How to get that?
Thanks.
Here's one option using a correlated subquery:
SELECT a.id, SUM(ash.amount_spend) AS spend_total,
(SELECT amount_spend
FROM account_spend_history as ash2
WHERE ash2.account_id = a.id
ORDER BY ash2.id DESC LIMIT 1) as last_spend
FROM accounts as a
INNER JOIN account_spend_history AS ash ON ash.account_id = a.id
GROUP BY a.id
You can get the MAX(ash.id) as well in your query and then use it to join back to account_spend_history table:
SELECT id, spend_total, amount_send as last_spend
FROM (
SELECT a.id, SUM(ash.amount_spend) AS spend_total, MAX(ash.id) AS ash_id
FROM accounts as a
INNER JOIN account_spend_history AS ash ON ash.account_id = a.id
GROUP BY a.id) AS t1
INNER JOIN account_spend_history AS ash ON ash.id = t1.ash_id
You can use a in clause and subquery
SELECT a.id, SUM(ash.amount_spend) AS spend_total, x.last_spend
FROM accounts as a
INNER JOIN account_spend_history AS ash ON ash.account_id = a.id
INNER JOIN (
select account_id, last_spend, start_date
from account_spend_history
where (start_date, acoount_id) in (
select max(start_date), account_id
from account_spend_history
group by account_id
)
) x on x.id = a.id
GROUP BY a.id
The intersect keyword is not available in mysql. I want to know how to implement the following in mysql db. My tables are:
customer(cid,city,name,state)
orders(cid,oid,date)
product(pid,price,productname)
lineitem(lid,pid,oid,totalquantity,totalprice)
I want the products bought by all the customers of a particular city 'X'. i.e. every customer in city 'x' should have bought the product. I managed to select the oid's and the pid's of customers living in that particular city. Now I should select the pid's which is present in all the oid's.
Example.
Oid Pid
2400 1
2400 2
2401 3
2401 1
2402 1
2403 1
2403 3
The answer from the above input should be 1 because it is present in all oid's. The query which I used to get the oid's and pid's:
select t.oid,l.pid
from lineitem l
join (select o.oid,c1.cid
from orders o
join (select c.cid
from customer c
where c.city='X') c1
where o.cid=c1.cid) t on l.oid=t.oid
Now I need to intersect all the oid's and get the result.The query should not be dependent on data.
Try:
select pid, count(*)
from (select t.oid, l.pid
from lineitem l
join (select o.oid, c1.cid
from orders o
join (select c.cid from customer c where c.city = 'X') c1
where o.cid = c1.cid) t
on l.oid = t.oid) x
group by pid
having count(*) = (select count(*)
from (select distinct oid
from lineitem l
join (select o.oid, c1.cid
from orders o
join (select c.cid
from customer c
where c.city = 'X') c1
where o.cid = c1.cid) t
on l.oid = t.oid) y) z
I think you can achieve what you want by using IN
Sorry in advance for an ambiguous title, but I can't think of a good one.
I have 2 tables:
bookings(booking_id, customer_id)
charges(customer_id, booking_id, amount)
where in charges table, either booking_id or customer_id must be entered. Not both.
I'm trying to get amount that are associated with a customer_id
Because the customer_id's are null sometimes in charges table, I have to use booking_id to acquire customer_id through bookings table.
So, I had a query like this:
SELECT c.amount
FROM charges as c, bookings as b
WHERE (c.customer_id = 1234) OR
(c.customer_id = null AND c.booking_id = b.booking_id AND b.customer_id = 1234)
However, it seems to create an infinite loop.
Any suggestions?
Thanks,
The problem is that you are doing a cross join (cartesian product), based on the structure of your where clause.
A better approach is to use left outer join (and proper join syntax). So, join to the bookings table, if it exists. Then use or in the where clause to look for a match on the customer_id in either place:
SELECT c.amount
FROM charges as c left outer join
bookings as b
on c.booking_id = b.booking_id
WHERE (c.customer_id = 1234) OR (b.customer_id = 1234)
Why you don't use a JOIN ? like
SELECT c.amout
FROM charges AS c
LEFT JOIN bookings AS b ON c.bookin_id = b.booking_id
WHERE c.customer_id = 1234 OR b.customer_id = 1234
SELECT amount, customer_id from charges where customer_id = 1234
UNION
select amount, b.customer_id from charges c, bookings b where b.booking_id = c.booking_id and c.customer_id is null and b.customer_id = 1234
Not sure how to write this join for 2 tables. Here is some sample data to illustrate:
orders
-----------------------
| order_id | customer |
-----------------------
ABC12345 1
ABC12346 4
ABC12347 3
ABC12348 2
ABC12349 2
ABC12350 3
customers
-----------------------------------
| id | name | email |
-----------------------------------
1 James james#gmail.com
2 Alice alice#hotmail.com
3 Jimbo james#gmail.com
4 Jim james#gmail.com
5 Lucy lucy#yahoo.com
I have an order_id, which I already know. Let's use the first one in the table: ABC12345. As you can see, the customer ID is 1, so that order was placed by James. Now sometimes James has ordered again using different names but we know it's him because of his email address.
So how do I retrieve all of James' orders based on his email address of james#gmail.com, if I know one of his order numbers (ABC12345)?
Edit: Not sure I stressed this enough... James has ordered 3 times, using the same email address but names of James, Jim and Jimbo. I need all of his orders using james#gmail.com as the email address.
SELECT o2.order_id
FROM orders o1
INNER JOIN customers c1
ON o1.customer = c1.id -- get the customer for the first order
INNER JOIN customers c2
ON c1.email = c2.email -- find all customers with same email
INNER JOIN orders o2
ON c2.id = o2.customer -- find all orders for those customers
WHERE o1.order_id = 'ABC12345'
You can use this:
SELECT order_id
FROM orders
WHERE customer IN (
SELECT id
FROM customers
WHERE email = (SELECT c.email FROM customers c JOIN orders o ON c.id = o.customer WHERE o.order_id = 'ABC12345')
)
You need to first quantify the person of the order to the customer table... Then, get all customer IDs by that same email... THEN get the orders that qualify those customer IDs.
select o2.*
from orders o2
JOIN ( select c2.ID
from customers c2
join ( select c1.email
from orders o
join customers c1
on o.Customer = c1.ID
where
o.order_id = 'ABC12345' ) FoundTheEmail
on c2.email = FoundTheEmail.email
) as SameCustomerEMail
on o2.Customer = SameCustomerEMail.ID
SELECT order_id
FROM orders
WHERE customer IN (SELECT customer
FROM orders
WHERE order_id = 'ABC12345')
try this since james has only one order
SELECT orders.order_id, customers.name, customers.email
FROM orders
INNER JOIN customers ON customers.id = orders.customer
WHERE orders.orer_id = 'ABC12345'
The order ID is a UNIQUE number, then you will not have two orders with the same ID, why care about the customer name?
"Every order will have a Customer's ID."