Sql: select only value that join table has value equal to 1 - mysql

I have these tables in mysql
ADS
ID
1
2
PAYMENTS
id ads_id
1 1
2 1
3 1
4 2
5 2
INSTALLMENTS
id Payment_id paid
1 1 1
2 1 0
3 2 1
4 2 1
5 3 1
6 4 0
7 4 1
8 5 0
I want to get count of ads that have only payments with all installments.paid = 1.
As an example, return value is 2 for ads.id = 1 (only payment.id 2 AND 3 has all installments.paid = 1) and 0 for ads.id = 0
I tried with
SELECT ads.id AS id,
(
select count(*)
from payments
where
(SELECT count(*)
FROM installments
where (installments.payment_id = payments.id AND (installments.paid = 0))) <1
AND payments.ad_id = ads.id
)
FROM ads
LEFT JOIN payments ON ads.id = payments.ad_id
LEFT JOIN installments ON installments.payment_id = payments.id
GROUP BY ads.id
But doesn't work

One way to approach this is using group by and having. To get the ad ids, you don't actually need the ads table, because installments has this information:
select i.ads_id
from installments i join
payments p
on i.payment_id = p.id
group by i.ads_id
having min(i.paid) = 1 and min(i.paid) = max(i.paid);
Note that this is checking both the minimum and maximum value -- just in case some other value were to creep in. If the value could be NULL, you would also want and count(*) = count(i.paid).
Another approach to this would just use not exists or not in:
select a.*
from ads a
where not exists (select 1
from installments i join
payments p
on i.payment_id = p.id
where p.ads_id = a.id and i.paid <> 0
);

Related

How can I retrieve Similar Orders In Mysql?

i need a query that should first look the oldest order which has status 0 (zero). and retrieves all the similar orders of that kind(matches exact total qty, itemSku and number of distinct items ordered).
***OrdersTable***
ID OrderNumber CustomerId Status created_at
1 123456 1 0 2018-01-01
2 234567 1 0 2018-01-02
3 345678 1 0 2018-01-03
4 456789 1 0 2018-01-04
***PurchasedProductsTable***
OrderId itemSku Qty
1 1000001 1
1 1000002 2
2 1000001 3
3 1000001 1
3 1000002 2
4 1000001 3
In the above table the query should first look at the oldest (created_at ASC) order (i.e with Id 1) having status 0 (in order table). and along with that order it should retrieves all the other orders that matches the same itemSku, qty and total distinct items count (in purchasedProducts table).
here order 1 and 3 matches the same itemSKu (1000001 and 1000002) and qty ( 1 and 2) and both have (2) distinct items count respectively so order 1 and 3 should be retrived at first.and when i marked order 1 and 3 as shipped (i.e chang status to 2).
and if i run query again it should retrive similar oders. now order 2 and 4 as order 2 and 4 are similar orders. (have same itemSkus (1000001, Qty (3) and distinct items count (1)).
please help thanks
You have to go trough your tables two times :)
Something like this :
SELECT DISTINCT O2.ID
FROM OrdersTable O1
INNER JOIN PurchasedProductsTable P1 ON O1.ID = P1.OrderId
INNER JOIN PurchasedProductsTable P2 ON P1.itemSku = P2.itemSku
AND P1.Qty = P2.Qty
INNER JOIN OrdersTable O2 ON O2.ID = P2.OrderId
WHERE O1.ID =
(SELECT ID FROM OrdersTable WHERE Status = 0
ORDER BY created_at ASC LIMIT 1)
AND (SELECT COUNT(*) FROM PurchasedProductsTable WHERE OrderId = O1.ID)
= (SELECT COUNT(*) FROM PurchasedProductsTable WHERE OrderId = O2.ID)
ORDER BY O2.ID ASC;
https://www.db-fiddle.com/f/65t9GgSfqMpzNVgnrJp2TR/2
You can get the earliest order via a limit and ordered by the date.
Then you can left join to get that order and any other order that at least has the same items.
Then once you have those order id's from the sub-query result, you can get the order details.
SELECT o.*
FROM
(
SELECT DISTINCT ord2.ID as OrderId
FROM
(
SELECT ID, CustomerId, Status
FROM OrdersTable
WHERE Status = 0
ORDER BY created_at
LIMIT 1
) AS ord1
JOIN PurchasedProductsTable AS pprod1
ON pprod1.OrderId = ord1.ID
LEFT JOIN OrdersTable ord2
ON ord2.CustomerId = ord1.CustomerId
AND ord2.Status = ord1.Status
LEFT JOIN PurchasedProductsTable pprod2
ON pprod2.OrderId = ord2.ID
AND pprod2.itemSku = pprod1.itemSku
AND pprod2.Qty = pprod1.Qty
GROUP BY ord1.CustomerId, ord1.ID, ord2.ID
HAVING COUNT(pprod1.itemSku) = COUNT(pprod2.itemSku)
) q
JOIN OrdersTable AS o ON o.ID = q.OrderId;
Test on RexTester here

How to get sum of amount from multiple accounts which return by join

I have 3 tables like:
owner_details:-
owner_id owner_name
---------------------
1 A
2 B
3 C
-------------------
vehicle_owner:-
v_id vehicle_id owner_id
-------------------------
1 1 1
2 2 2
3 4 1
4 3 1
5 5 3
transaction:-
id v_id amount transaction_type
--------------------------------
1 1 100 0
2 2 250 1
3 1 150 1
4 3 450 1
5 1 200 0
6 4 300 1
7 5 150 0
8 5 200 1
transaction_type= 0 then (-) transaction_type=1 then (+)
Owner A (1) have 3 vehicles with v_id (1,3,4) in table vehicle_owner.
v_id (1,3,4) have 5 entries in table transaction (1,3,4,5,6) with sum of amount 600 (-100+150+450-200+300)
Now I want listing like this:-.
owner_id owner_name amount
---------------------
1 A 600
2 B 250
3 C 50
-------------------
You can use the following query:
SELECT od.owner_id, od.owner_name, SUM(t.amount) AS amount
FROM owner_details od INNER JOIN vehicle_owner vo ON od.owner_id = vo.owner_id
INNER JOIN `transaction` t ON vo.v_id = t.v_id
GROUP BY od.owner_id
If you want to use the additional transaction_type you can use the following:
SELECT od.owner_id, od.owner_name, SUM(CASE WHEN t.transaction_type = 0 THEN t.amount * -1 ELSE t.amount END) AS amount
FROM owner_details od INNER JOIN vehicle_owner vo ON od.owner_id = vo.owner_id
INNER JOIN `transaction` t ON vo.v_id = t.v_id
GROUP BY od.owner_id
demo: http://sqlfiddle.com/#!9/c5f8d/1/1
Try this:
SELECT A.owner_id, A.owner_name, SUM(IFNULL(amount,0)) AMOUNT
FROM owner_details A LEFT JOIN
vehicle_owner B
ON A.owner_id=B.owner_id
LEFT JOIN `transaction` C
ON C.v_id=B.v_id
GROUP BY A.owner_id, A.owner_name;
It works for me
SELECT od.owner_id,
od.owner_name,
Sum(t.amount) AS amount
FROM owner_details od
INNER JOIN vehicle_owner vo
ON od.owner_id = vo.owner_id
INNER JOIN (SELECT v_id,
Coalesce(Sum(CASE
WHEN type = 0 THEN -amount
ELSE +amount
end), 0.0) AS amount
FROM `transaction`
GROUP BY v_id) t
ON vo.v_id = t.v_id
GROUP BY od.owner_id
Thanks Sebastian Brosch for quick response !!!

MYSQL LEFTJOIN multiple ids same table

Im trying to get a combination of ids from a table like this:
Table activation:
user_id product_id reseller_id range_id Name
-------------------------------------------------
1 1 5 2 Oscar
1 1 5 3 Luis
2 1 5 4 Julian
Table prices (compType_id = reseller_id):
product_id compType_id price range_id
------------------------------------------------
1 5 38.60 2
1 5 48.60 3
1 5 58.60 4
Table users:
user_id name
----------------
1 lloyd
2 Mark
I want to select the activation Name and the price of prices based on the user_id.
How can i do that?
I tried something like this:
SELECT a.name
(SELECT price FROM prices WHERE product_id = 1 AND range_id =
AND compType_id = 5) AS price
FROM activation AS a
LEFT JOIN users AS u ON u.user_id = a.u_id
WHERE u.user_id = 1
The price columns have the same value in each row.
name price
Oscar 21.30
Luis 21.30
How can i change it to show the correct price?
I solved it with something like this:
SELECT a.company, a.name, a.email, a.phone, a.ruc, a.code, a.active,
a.numlic, (SELECT p.price FROM prices AS p WHERE p.product_id =
a.product_id AND p.range_id = a.range_id AND p.compType_id = c.type_id)
AS price
FROM activation AS a
LEFT JOIN users AS u ON u.user_id = a.u_id
LEFT JOIN companies AS c ON a.reseller_id = c.id
WHERE u.user_id = 1

MySQL - Display null column from child table if all values are not distinct

I have the following tables, for example:
invoices
ID Name
1 A
2 B
3 C
4 D
5 E
transactions
ID Invoice_ID User_ID
1 1 10
2 1 10
3 1 10
4 2 30
5 3 20
6 3 40
7 2 30
8 2 30
9 4 40
10 3 50
Now I want to make a select that will pull the invoices and the user_id from the related transactions, but of course if I do that I won't get all the ids, since they may be distinct but there will be only one column for that. What I want to do is that if there are distinct User_ids, I will display a pre-defined text in the column instead of the actual result.
select invoices.id, invoices.name, transactions.user_id(if there are distinct user_ids -> return null)
from invoices
left join transactions on invoices.id = transactions.invoice_id
and then this would be the result
ID Name User_ID
1 A 10
2 B 30
3 C null
4 D 40
5 E null
Is this possible?
You can do the following :
select
invoices.id,
invoices.name,
IF (
(SELECT COUNT(DISTINCT user_id) FROM transactions WHERE transactions.invoice_id = invoices.id) = 1,
(SELECT MAX(user_id) FROM transactions WHERE transactions.invoice_id = invoices.id),
null
) AS user_id
from invoices
Or, alternatively, you can use the GROUP_CONCAT function to output a comma-separated list of users for each invoice. It is not exactly what you asked, but maybe in fact it will be more useful :
select
invoices.id,
invoices.name,
GROUP_CONCAT(DISTINCT transactions.user_id SEPARATOR ',') AS user_ids
from invoices
left join transactions on invoices.id = transactions.invoice_id
group by invoices.id
Try somethingh like:
select i.id, i.name, t.user_id
from invoices i left join
(
select invoice_ID, User_ID
from transactions
group by invoice_ID
having count(invoice_ID)=1
) t on i.id=t.invoice_id
SQL fiddle
You could list all the transactions that have multiple user ids, like this:
select invoices.id, invoices.name, null
from invoices
left join transactions on invoices.id = transactions.invoice_id having count(distinct transactions.user_id) > 1
Also, I think this CASE might suit your needs here:
select invoices.id, invoices.name,
case when count(distinct transactions.user_id) > 1 then null else transactions.user_id end
from invoices
left join transactions on invoices.id = transactions.invoice_id
group by invoices.id
although, I'm not sure this is syntactically correct

mySQL - GROUP BY but get the most recent row

I've got a budget table:
user_id product_id budget created
-----------------------------------------------------------------
1 1 300 2011-12-01
2 1 400 2011-12-01
1 1 500 2011-12-03
2 2 400 2011-12-04
I've also got a manager_user table, joining a manager with the user
user_id manager_id product_id
------------------------------------
1 5 1
1 9 2
2 5 1
2 5 2
3 5 1
What I'd like to do is grab each of the user that's assigned to Manager #5, and also get their 'budgets'... but only the most recent one.
Right now my statement looks like this:
SELECT * FROM manager_user mu
LEFT JOIN budget b
ON b.user_id = mu.user_id AND b.product_id = mu.product_id
WHERE mu.manager_id = 5
GROUP BY mu.user_id, mu.product_id
ORDER BY b.created DESC;
The problem is it doesn't pull the most recent budget. Any suggestions? Thanks!
To accomplish your task you can do as follows:
select b1.user_id,
b1.budget
from budget b1 inner join (
select b.user_id,
b.product_id,
max(created) lastdate
from budget b
group by b.user_id, b.product_id ) q
on b1.user_id=q.user_id and
b1.product_id=q.product_id and
b1.created=q.lastdate
where b1.user_id in
(select user_id from manager_user where manager_id = 5);
I'm assuming here that your (user_id, product_id, created) combination is unique.
For what it's worth, here's the code that returned what I was looking for:
SELECT DISTINCT(b1.id),mu.user_id,mu.product_id,b1.budget,b1.created
FROM budget b1
INNER JOIN (
SELECT b.user_id, b.product_id, MAX(created) lastdate
FROM budget b
GROUP BY b.user_id, b.product_id) q
ON b1.user_id=q.user_id AND
b1.product_id=q.product_id AND
b1.created=q.lastdate
RIGHT JOIN manager_user mu
ON mu.user_id = b1.user_id AND
mu.product_id = b1.product_id
WHERE mu.manager_id = 5;
Thanks for the help Andrea!