MySQL Left Join with Specific Condition - mysql

I have following tables that manage revenue
revenue Table
+------------+--------+--------+
| revenue_id | amount | status |
+------------+--------+--------+
| 1 | 45000 | 1 |
| 2 | 25000 | 1 |
| 3 | 67000 | 1 |
| 4 | 22000 | 1 |
| 5 | 32000 | 0 |
+------------+--------+--------+
bank Table
+---------+--------+-------------+-------------+
| bank_id | ref_no | bank_amount | bank_status |
+---------+--------+-------------+-------------+
| 1 | 2 | 23000 | Pending |
| 2 | 3 | 67000 | Confirmed |
| 3 | 4 | 22000 | Confirmed |
+---------+--------+-------------+-------------+
02) If a revenue as mentioned in the revenue table has banked, it is recorded in the bank table. After that, the amounts in two tables are equal, the bank status may be into "Confirmed".
03) So, I need to get Confirmed records only as following by joining above two tables
Desired Output
+------------+--------+-------------+-------------+
| revenue_id | amount | bank_amount | bank_status |
+------------+--------+-------------+-------------+
| 3 | 67000 | 67000 | Confirmed |
| 4 | 22000 | 22000 | Confirmed |
+------------+--------+-------------+-------------+
Desired Output-02
+------------+--------+-------------+-------------+
| revenue_id | amount | bank_amount | bank_status |
+------------+--------+-------------+-------------+
| 1 | 45000 | | |
| 2 | 25000 | 23000 | Pending |
| 3 | 67000 | 67000 | Confirmed |
| 4 | 22000 | 22000 | Confirmed |
+------------+--------+-------------+-------------+
Desired Output-03
+------------+--------+-------------+-------------+
| revenue_id | amount | bank_amount | bank_status |
+------------+--------+-------------+-------------+
| 1 | 45000 | | |
| 2 | 25000 | 23000 | Pending |
+------------+--------+-------------+-------------+
04) To get the desired output I used the following query
select revenue.revenue_id, revenue.amount, bank.bank_amount, bank.bank_status
from revenue
left join bank on bank.ref_no = revenue.revenue_id
where revenue.status = 1 and bank.bank_status = "Confirmed"
05) But did't get the expected result. It generated only the empty result. I can not understand what I am going wrong. Can any one help me ?

You have to use Inner Join instead of Left JOIN for your expected output.
SELECT revenue.revenue_id,
revenue.amount,
bank.bank_amount,
bank.bank_status
FROM revenue
INNER JOIN bank ON bank.ref_no = revenue.revenue_id
WHERE revenue.status = 1
AND bank.bank_status = "Confirmed"
DEMO

select revenue.revenue_id, revenue.amount, bank.bank_amount, bank.bank_status
from revenue
Inner join (select *
From bank
Where bank_status = "Confirmed") bank
on bank.ref_no = revenue.revenue_id

You have to use the first bank table and then revenue table for left join .
Because in left join all rows will be returned even without matches.
So, use query like this.
select revenue.revenue_id, revenue.amount, bank.bank_amount, bank.bank_status
from bank
left join revenue on bank.ref_no = revenue.revenue_id
where revenue.status = 1 and bank.bank_status = "Confirmed"

Related

INNER JOIN shows only first row in table

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 | mutation |
|-----------------------------------|
| 1 | 1 | 100 |
| 2 | 1 | 200 |
| 3 | 2 | 500 |
| 4 | 1 | 500 |
-------------------------------------
What I want to do is I want to select all the rows in table scu_banks and show the total sum of mutations. The data should be represented like:
--------------------------------------------------------------
| scu_banks.type | scu_banks.name | total | scu_banks.id |
--------------------------------------------------------------
| 1 | One | € 800.00 | 1 |
| 1 | Two | € 500.00 | 2 |
| 2 | Three | € 0.00 | 3 |
| 3 | Four | € 0.00 | 4 |
--------------------------------------------------------------
When I run my sql statement I get the following data:
---------------------------------------------------------------
| scu_banks.type | scu_banks.name | total | scu_banks.id |
--------------------------------------------------------------
| 1 | One | € 1300.00 | 1 |
---------------------------------------------------------------
The data I get in this case is not correct. € 1300.00 it the total of all the mutations 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 scu_banks.type,
scu_banks.name,
CONCAT('€ ', FORMAT(IFNULL(SUM(scu_statement.mutations), 0),2)) AS total,
scu_banks.id
FROM scu_banks
INNER JOIN scu_statement
ON scu_banks.id = scu_statement.code
Do the aggregation in a subquery and left join it to the banks.
SELECT b.type "scu_banks.type",
b.name "scu_banks.name",
concat('€ ', format(coalesce(x.mutation, 0), 2)) "total",
b.id "scu_banks.id"
FROM scu_banks b
LEFT JOIN (SELECT s.code,
sum(s.mutation) mutation
FROM scu_statement s
GROUP BY s.code) x
ON x.code = b.id;

Left joins, i need an explanation about a code

i am watching a tutorial. There is a code which i don't understand what is supposed to do.
$sql = 'SELECT p.*,
a.screen_name AS author_name,
c.name AS category_name
FROM
posts p
LEFT JOIN
admin_users a ON p.author_id = a.id
LEFT JOIN
categories c ON p.category_id = c.id
WHERE
p.id = ?';
I read about the left joins but i didn't understand them. Can somebody please explain me the code i shared.
Thanks in advance!
Imagine you have two tables. One that stores the information about the programmers on your website, and the other table that keeps track of their online purchases.
PROGRAMMERS Table
+--------------------------------------------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Desire | 32 | 123 fake s| 3000.00 |
| 2 | Jamin | 25 | 234 fake s| 2500.00 |
| 3 | Jon | 23 | 567 fake s| 2000.00 |
| 4 | Bob | 30 | 789 fake s| 1500.00 |
| 5 | OtherGuy | 31 | 890 fake s| 1000.00 |
| 6 | DudeMan | 32 | 901 fake s| 500.00 |
+--------------------------------------------+
PURCHASES Table
+---------------------------------------------+
| ORDER_ID | PROG_ID | DATE | PRICE |
+-------------+---------+---------------------|
| 1 | 1 | 1-1-2017 | 100 |
| 2 | 2 | 1-2-2017 | 200 |
| 3 | 6 | 1-3-2017 | 300 |
+---------------------------------------------|
You decide you need to make a new table to consolidate this information to a table that contains
certain columns you want.
For example, you figure it would be nice for shipping purposes to have a table
that has the ID, the NAME, the PRICE, and the DATE columns.
Currently, the tables we have don't display all of that in a single table.
If we were to LEFT JOIN these tables, we would end up filling the desired columns
with NULL values where there is no information to join.
SELECT ID, NAME, PRICE, DATE
FROM PROGRAMMERS
LEFT JOIN PURCHASES
ON PROGRAMMERS.ID = PURCHASES.PROG_ID;
Notice that I'm selecting the columns I want from the starting table, then joining the right table
even though there might be missing information.
RESULTING TABLE
+-------------------------------------+
| ID | NAME | PRICE | DATE |
+----+----------+-----------------+---+
| 1 | Desire | 100 | 1-1-2017 |
| 2 | Jamin | 200 | 1-2-2017 |
| 3 | Jon | NULL | NULL |
| 4 | Bob | NULL | NULL |
| 5 | OtherGuy | NULL | NULL |
| 6 | DudeMan | 300 | 1-3-2017 |
+-------------------------------------+
For a visual representation of the difference between SQL JOINs check out
https://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins .

Query is selecting count from joined table

I have a shipments table, and a shipments detail table. A shipment generally ships multiple cartons. I am trying to select a count of the shipment table and sum the quantity from the detail table. But my values are being selected from the joined table.
ex. count = 7, when count should be 4 from my shipment table
SELECT ss.tenant_id,
ss.order_id,
COUNT(ss.shipment_number),
SUM(sd.qty_shipped)
FROM shipment ss
LEFT JOIN detail sd
ON ss.id = sd.shipment_id
GROUP BY
ss.order_id,
ss.tenant_id;
output -->
tenant_id | order_id | count | sum
-----------+----------+-------+------
1 | 2573 | 7 | 1350
Data set -->
shipment
id | shipment_number | shipment_status | tracking_number | shipping_cost
------+-----------------+----------------+----------------+---------------
8332 | 1000048 | confirmed | 123 | 10.00
8333 | 1000049 | confirmed | 123 | 10.00
8334 | 1000050 | confirmed | 123 | 10.00
8335 | 1000051 | confirmed | 123 | 10.00
detail
id | carton_number | qty_shipped | order_id | shipment_id
-------+---------------+-------------+----------+------------
14654 | 1 | 200 | 2573 | 8332
14655 | 2 | 200 | 2573 | 8332
14656 | 1 | 200 | 2573 | 8333
14657 | 1 | 200 | 2573 | 8334
14658 | 2 | 200 | 2573 | 8334
14659 | 1 | 150 | 2573 | 8335
14660 | 2 | 200 | 2573 | 8335
I had to add distinct in my count.
select ss.tenant_id,
ss.order_id,
count(distinct ss.shipment_number),
sum(sd.qty_shipped)
from shipping_shipment ss
left join shipping_shipmentdetail sd
on ss.id = sd.shipment_id
GROUP BY
ss.order_id,
ss.tenant_id;

Mysql returning incorrect COUNT when using more than one JOIN?

I have 3 tables: NAMES, REGISTRATIONS, and RENEWALS. I'm using LEFT JOIN to join the 3 tables with a common ID.
I need to count the number of REGISTRATIONS of each user, as well as the number of RENEWALS. I've tried using different options in the GROUP BY field, but none seemed to work.
Here's the SELECT statement:
SELECT
names.name_id AS 'Names ID'
,names.name AS Name
,count(registrations.date) AS Registrations
,count(renewals.date) AS Renewals
FROM names
LEFT JOIN registrations
ON names.name_id = registrations.name_id
LEFT JOIN renewals
ON renewals.name_id = registrations.name_id
GROUP BY names.name_id, registrations.name_id, renewals.name_id;
And here are the 3 tables:
TABLE: names
+---------+------+
| name_id | name |
+---------+------+
| 1 | Ana |
| 2 | John |
| 3 | Paul |
+---------+------+
TABLE: registrations
+-----------------+---------+---------------------+-------+
| registration_id | name_id | date | value |
+-----------------+---------+---------------------+-------+
| 1 | 1 | 2014-01-30 13:15:02 | 15 |
| 2 | 2 | 2014-05-01 18:01:44 | 15 |
| 3 | 2 | 2014-07-08 15:10:43 | 20 |
| 4 | 3 | 2012-09-28 17:45:32 | 15 |
| 5 | 3 | 2014-01-09 18:26:14 | 20 |
| 6 | 3 | 2015-01-10 13:22:01 | 25 |
+-----------------+---------+---------------------+-------+
TABLE: renewals
+------------+---------+---------------------+-------+
| renewal_id | name_id | date | value |
+------------+---------+---------------------+-------+
| 1 | 1 | 2015-01-30 00:00:00 | 5 |
| 2 | 1 | 2016-02-12 00:00:00 | 5 |
| 3 | 1 | 2015-06-01 00:00:00 | 5 |
| 4 | 1 | 2013-11-24 00:00:00 | 5 |
| 5 | 2 | 2015-01-27 00:00:00 | 5 |
+------------+---------+---------------------+-------+
Here's the INCORRECT result I'm getting:
+----------+------+---------------+----------+
| Names ID | Name | Registrations | Renewals |
+----------+------+---------------+----------+
| 1 | Ana | 4 | 4 |
| 2 | John | 2 | 2 |
| 3 | Paul | 3 | 0 |
+----------+------+---------------+----------+
The CORRECT result I was expecting would be:
+----------+------+---------------+----------+
| Names ID | Name | Registrations | Renewals |
+----------+------+---------------+----------+
| 1 | Ana | 1 | 4 |
| 2 | John | 2 | 1 |
| 3 | Paul | 3 | 0 |
+----------+------+---------------+----------+
How can I fix the query to get a correct result?
Try this:
SELECT
names.name_id AS 'Names ID'
,names.name AS Name
,count(distinct registrations.registration_id) AS Registrations
,count(distinct renewals.renewal_id) AS Renewals
FROM names
LEFT JOIN registrations
ON names.name_id = registrations.name_id
LEFT JOIN renewals
ON renewals.name_id = registrations.name_id
GROUP BY names.name_id, registrations.name_id, renewals.name_id;
Whenever I run into this type of issue, I find it helps to just run a select * query if your server can take it. Like this:
SELECT *
FROM names
LEFT JOIN registrations
ON names.name_id = registrations.name_id
LEFT JOIN renewals
ON renewals.name_id = registrations.name_id ;
That will let you see what you are really counting.
Your query is executed just fine.
After the first join you have 1 entry for Ana, 2 entries for John and 3 for Paul.
After the seconds join the one entry for Ana is duplicated 4 times and joined (concatenated) with the 4 renewals. If you now count the registration dates for Ana you get 4. That is where your "errors" come from.
You could for example count the distinct dates to fix it.

Select total members and amount paid

I need help generating SQL for MySQL database.
I have three tables:
Organisations
Members
Payments
Organisations table:
+------------+---------+--------+
| id | name |website |
+------------+---------+--------+
| 1 | AAA | a.com |
|-------------------------------+
| 2 | BBB | b.com |
+------------+---------+--------+
Members table:
+------------+-------------------+--------+-----------------+-----------+
| id | organisation_id |name | Payment_confirm | join_date |
+------------+-------------------+--------+-----------------+-----------+
| 1 | 1 | james | 1 | 2013-8-02 |
|-----------------------------------------+-----------------+-----------+
| 2 | 1 | Jimmy | 0 | 2013-6-25 |
+------------+-------------------+--------+-----------------+-----------+
| 3 | 2 | Manny | 1 | 2013-07-02|
|-----------------------------------------+-----------------+-----------+
| 4 | 1 | Kim | 1 | 2013-09-02|
+------------+-------------------+--------+-----------------+-----------+
Payments table:
+------------+-------------------+--------+-----------------+----------------+
| id | member_id |amount | transaction_id | transferred_at |
+------------+-------------------+--------+-----------------+----------------+
| 1 | 1 | 100 | T1001 | 2013-8-03 |
|-----------------------------------------+-----------------+--------------- +
| 2 | 2 | 0 | null | Null |
+------------+-------------------+--------+-----------------+----------------+
| 3 | 3 | 200 | T1002 | Null |
|-----------------------------------------+-----------------+----------------+
| 4 | 4 | 50 | T1005 | 2013-09-05 |
+------------+-------------------+--------+-----------------+----------------+
How can I select the following?
Expecting the following output:
+------------+-------------------+--------+-----------------+---------------+--------------+
| Org name | Revenue |untransferred amount | Total members | last 30 days |
+------------+-------------------+--------------------------+---------------+--------------+
| AAA | 150 | 0 | 3 | 2 |
|-----------------------------------------------------------+---------------+--------------+
| BBB | 200 | 200 | 1 | 0 |
+------------+-------------------+--------------------------+---------------+--------------+
Org name = organisation name
Revenue = Total amount received
untransferred amount = transferred_at is null (payments table)
Total members = total members joined till today
last 30 days = total members joined last 30 days
You need to join your tables, group the results and select the desired logic:
SELECT org.name,
SUM(pmt.amount) AS revenue,
SUM(IF(pmt.transferred_at IS NULL, pmt.amount, 0)) AS untransferred
FROM Organisations org
JOIN Members mem ON mem.organisation_id = org.id
JOIN Payments pmt ON pmt.member_id = mem.id
GROUP BY org.id
See it on sqlfiddle.
select o.name,
sum(amount) as Revenue,
sum(if(transferred_at is null, amount, 0)) as untransfered_ammt,
sum(if(join_date>=curdate() - interval 30 day, 1, 0)) as last_30_d
from organisations o
inner join members m on o.id=m.organisation_id
inner join payments p on p.member_id=m.member_id
group by 1