how can get with multipule columns with group by in sql server - sql

Please need help if possible.
select a.* from (
select u.user_guid,u.user_name,u.user_email,u.user_type,
uinf.user_info_fname,uinf.user_info_lname,uinf.user_info_address,img.image_type,img.image_location,
v.visitor_datetime,v.visitor_duration,v.visitor_ip,v.media_guid
from
tb_visitors_log as v
left outer join tb_media as m on v.media_guid=m.media_guid left outer join
tb_users as u on v.user_guid=u.user_guid left outer join
tb_user_info as uinf on uinf.user_guid=u.user_guid
left outer join tb_images as img on img.image_guid=uinf.user_info_thumbnail
where v.media_guid=#media_guid and uinf.user_info_lname like concat('%',#searchvalue,'%')) as a
order by a.visitor_datetime desc
I want the output to be grouped by a.user_guid. In MySQL I do this:
select a.* from (select u.user_guid,u.user_name,u.user_email,u.user_type,
uinf.user_info_fname,uinf.user_info_lname,uinf.user_info_address,img.image_type,img.image_location,
v.visitor_datetime,v.visitor_duration,v.visitor_ip,v.media_guid
from
tb_visitors_log as v
left outer join tb_media as m on v.media_guid=m.media_guid left outer join
tb_users as u on v.user_guid=u.user_guid left outer join
tb_user_info as uinf on uinf.user_guid=u.user_guid
left outer join tb_images as img on img.image_guid=uinf.user_info_thumbnail
where v.media_guid=P_media_guid and uinf.user_info_lname like concat('%',P_searchvalue,'%')
order by v.visitor_datetime desc
) as a group by a.user_guid;
But in SQL Server 2012 I can't do that.
this my resultt https://plus.google.com/u/1/photos/104984108592274133808/albums/6044709663274953441/6044709665297999426?pid=6044709665297999426&oid=104984108592274133808
and this is the one i want to have https://plus.google.com/u/1/photos/104984108592274133808/albums/6044709663274953441/6044709666972693378?pid=6044709666972693378&oid=104984108592274133808

I see this kind of misconception about GROUP BY very often (damn you, MySQL!).
You cannot output columns directly, unless they are in your GROUP BY clause, or unless you have some aggregate function on them. Simple example. Suppose your base table looks like this:
+--------+----------+-------+
| UserId | UserName | Value |
+--------+----------+-------+
| 1 | Alpha | 150 |
| 1 | Alpha | 110 |
| 1 | Alpha | 170 |
| 2 | Bravo | 240 |
| 3 | Charlie | 350 |
| 3 | Charlie | 330 |
+--------+----------+-------+
Now say you only want one row for each user. You would then try something like this:
SELECT * FROM MyTable GROUP BY UserId
This will not work, because the database doesn't know what to do with the 2 columns that you didn't group upon. Now, some database engines (MySQL, grrr!) lets you do this anyway, and for the UserName column, this would probably be fine, since there seems to be a 1:1 relation between UserId and UserName. But for each user, you need to decide what to do with the Value column, since it seems to contain different values for the same UserId (here, MySQL would just pick a random value).
This is where you need to specify an aggregate function, such as SUM(), MAX(), MIN(), etc... So say you just want the maximum value for each user, you would have to do this:
SELECT UserId, UserName, MAX(Value) AS [MaximumValue]
FROM MyTable
GROUP BY UserId, UserName
Note here, that I had to GROUP BY both the UserId and UserName columns - this is because the database engine does not know about the 1:1 relation between these columns. Each time you find yourself listing a lot of columns from the same table in the GROUP BY part of your query, it typically indicates bad data design, which is the case in my sample table, since the UserName-column contains redundant data.

This i my answer if any one cares
select distinct u.user_guid,u.user_name,u.user_email,u.user_type,
uinf.user_info_fname,uinf.user_info_lname,uinf.user_info_address,img.image_type,img.image_location,
v.visitor_datetime,v.visitor_duration,v.visitor_ip,v.media_guid
from tb_visitors_log as v
left outer join tb_media as m on v.media_guid=m.media_guid left outer join
tb_users as u on v.user_guid=u.user_guid left outer join
tb_user_info as uinf on uinf.user_guid=u.user_guid
left outer join tb_images as img on img.image_guid=uinf.user_info_thumbnail
where u.user_guid in(
select distinct u.user_guid
from
tb_visitors_log as v
left outer join tb_media as m on v.media_guid=m.media_guid left outer join
tb_users as u on v.user_guid=u.user_guid left outer join
tb_user_info as uinf on uinf.user_guid=u.user_guid
left outer join tb_images as img on img.image_guid=uinf.user_info_thumbnail
where uinf.user_info_fname like concat('%',#searchvalue,'%') and v.media_guid=#media_guid)
and v.visitor_datetime in
(select max(v.visitor_datetime) from tb_visitors_log as v
left outer join tb_media as m on v.media_guid=m.media_guid left outer join
tb_users as u on v.user_guid=u.user_guid left outer join
tb_user_info as uinf on uinf.user_guid=u.user_guid
left outer join tb_images as img on img.image_guid=uinf.user_info_thumbnail
where v.media_guid=#media_guid and uinf.user_info_fname like concat('%',#searchvalue,'%') group by v.user_guid)
and v.media_guid=#media_guid

Related

SQL: SELECT from different tables [duplicate]

What is a SQL JOIN and what are different types?
An illustration from W3schools:
What is SQL JOIN ?
SQL JOIN is a method to retrieve data from two or more database tables.
What are the different SQL JOINs ?
There are a total of five JOINs. They are :
1. JOIN or INNER JOIN
2. OUTER JOIN
2.1 LEFT OUTER JOIN or LEFT JOIN
2.2 RIGHT OUTER JOIN or RIGHT JOIN
2.3 FULL OUTER JOIN or FULL JOIN
3. NATURAL JOIN
4. CROSS JOIN
5. SELF JOIN
1. JOIN or INNER JOIN :
In this kind of a JOIN, we get all records that match the condition in both tables, and records in both tables that do not match are not reported.
In other words, INNER JOIN is based on the single fact that: ONLY the matching entries in BOTH the tables SHOULD be listed.
Note that a JOIN without any other JOIN keywords (like INNER, OUTER, LEFT, etc) is an INNER JOIN. In other words, JOIN is
a Syntactic sugar for INNER JOIN (see: Difference between JOIN and INNER JOIN).
2. OUTER JOIN :
OUTER JOIN retrieves
Either,
the matched rows from one table and all rows in the other table
Or,
all rows in all tables (it doesn't matter whether or not there is a match).
There are three kinds of Outer Join :
2.1 LEFT OUTER JOIN or LEFT JOIN
This join returns all the rows from the left table in conjunction with the matching rows from the
right table. If there are no columns matching in the right table, it returns NULL values.
2.2 RIGHT OUTER JOIN or RIGHT JOIN
This JOIN returns all the rows from the right table in conjunction with the matching rows from the
left table. If there are no columns matching in the left table, it returns NULL values.
2.3 FULL OUTER JOIN or FULL JOIN
This JOIN combines LEFT OUTER JOIN and RIGHT OUTER JOIN. It returns rows from either table when the conditions are met and returns NULL value when there is no match.
In other words, OUTER JOIN is based on the fact that: ONLY the matching entries in ONE OF the tables (RIGHT or LEFT) or BOTH of the tables(FULL) SHOULD be listed.
Note that `OUTER JOIN` is a loosened form of `INNER JOIN`.
3. NATURAL JOIN :
It is based on the two conditions :
the JOIN is made on all the columns with the same name for equality.
Removes duplicate columns from the result.
This seems to be more of theoretical in nature and as a result (probably) most DBMS
don't even bother supporting this.
4. CROSS JOIN :
It is the Cartesian product of the two tables involved. The result of a CROSS JOIN will not make sense
in most of the situations. Moreover, we won't need this at all (or needs the least, to be precise).
5. SELF JOIN :
It is not a different form of JOIN, rather it is a JOIN (INNER, OUTER, etc) of a table to itself.
JOINs based on Operators
Depending on the operator used for a JOIN clause, there can be two types of JOINs. They are
Equi JOIN
Theta JOIN
1. Equi JOIN :
For whatever JOIN type (INNER, OUTER, etc), if we use ONLY the equality operator (=), then we say that
the JOIN is an EQUI JOIN.
2. Theta JOIN :
This is same as EQUI JOIN but it allows all other operators like >, <, >= etc.
Many consider both EQUI JOIN and Theta JOIN similar to INNER, OUTER
etc JOINs. But I strongly believe that its a mistake and makes the
ideas vague. Because INNER JOIN, OUTER JOIN etc are all connected with
the tables and their data whereas EQUI JOIN and THETA JOIN are only
connected with the operators we use in the former.
Again, there are many who consider NATURAL JOIN as some sort of
"peculiar" EQUI JOIN. In fact, it is true, because of the first
condition I mentioned for NATURAL JOIN. However, we don't have to
restrict that simply to NATURAL JOINs alone. INNER JOINs, OUTER JOINs
etc could be an EQUI JOIN too.
Definition:
JOINS are way to query the data that combined together from multiple tables simultaneously.
Types of JOINS:
Concern to RDBMS there are 5-types of joins:
Equi-Join: Combines common records from two tables based on equality condition.
Technically, Join made by using equality-operator (=) to compare values of Primary Key of one table and Foreign Key values of another table, hence result set includes common(matched) records from both tables. For implementation see INNER-JOIN.
Natural-Join: It is enhanced version of Equi-Join, in which SELECT
operation omits duplicate column. For implementation see INNER-JOIN
Non-Equi-Join: It is reverse of Equi-join where joining condition is uses other than equal operator(=) e.g, !=, <=, >=, >, < or BETWEEN etc. For implementation see INNER-JOIN.
Self-Join:: A customized behavior of join where a table combined with itself; This is typically needed for querying self-referencing tables (or Unary relationship entity).
For implementation see INNER-JOINs.
Cartesian Product: It cross combines all records of both tables without any condition. Technically, it returns the result set of a query without WHERE-Clause.
As per SQL concern and advancement, there are 3-types of joins and all RDBMS joins can be achieved using these types of joins.
INNER-JOIN: It merges(or combines) matched rows from two tables. The matching is done based on common columns of tables and their comparing operation. If equality based condition then: EQUI-JOIN performed, otherwise Non-EQUI-Join.
OUTER-JOIN: It merges(or combines) matched rows from two tables and unmatched rows with NULL values. However, can customized selection of un-matched rows e.g, selecting unmatched row from first table or second table by sub-types: LEFT OUTER JOIN and RIGHT OUTER JOIN.
2.1. LEFT Outer JOIN (a.k.a, LEFT-JOIN): Returns matched rows from two tables and unmatched from the LEFT table(i.e, first table) only.
2.2. RIGHT Outer JOIN (a.k.a, RIGHT-JOIN): Returns matched rows from two tables and unmatched from the RIGHT table only.
2.3. FULL OUTER JOIN (a.k.a OUTER JOIN): Returns matched and unmatched from both tables.
CROSS-JOIN: This join does not merges/combines instead it performs Cartesian product.
Note: Self-JOIN can be achieved by either INNER-JOIN, OUTER-JOIN and CROSS-JOIN based on requirement but the table must join with itself.
For more information:
Examples:
1.1: INNER-JOIN: Equi-join implementation
SELECT *
FROM Table1 A
INNER JOIN Table2 B ON A.<Primary-Key> =B.<Foreign-Key>;
1.2: INNER-JOIN: Natural-JOIN implementation
Select A.*, B.Col1, B.Col2 --But no B.ForeignKeyColumn in Select
FROM Table1 A
INNER JOIN Table2 B On A.Pk = B.Fk;
1.3: INNER-JOIN with NON-Equi-join implementation
Select *
FROM Table1 A INNER JOIN Table2 B On A.Pk <= B.Fk;
1.4: INNER-JOIN with SELF-JOIN
Select *
FROM Table1 A1 INNER JOIN Table1 A2 On A1.Pk = A2.Fk;
2.1: OUTER JOIN (full outer join)
Select *
FROM Table1 A FULL OUTER JOIN Table2 B On A.Pk = B.Fk;
2.2: LEFT JOIN
Select *
FROM Table1 A LEFT OUTER JOIN Table2 B On A.Pk = B.Fk;
2.3: RIGHT JOIN
Select *
FROM Table1 A RIGHT OUTER JOIN Table2 B On A.Pk = B.Fk;
3.1: CROSS JOIN
Select *
FROM TableA CROSS JOIN TableB;
3.2: CROSS JOIN-Self JOIN
Select *
FROM Table1 A1 CROSS JOIN Table1 A2;
//OR//
Select *
FROM Table1 A1,Table1 A2;
Interestingly most other answers suffer from these two problems:
They focus on basic forms of join only
They (ab)use Venn diagrams, which are an inaccurate tool for visualising joins (they're much better for unions).
I've recently written an article on the topic: A Probably Incomplete, Comprehensive Guide to the Many Different Ways to JOIN Tables in SQL, which I'll summarise here.
First and foremost: JOINs are cartesian products
This is why Venn diagrams explain them so inaccurately, because a JOIN creates a cartesian product between the two joined tables. Wikipedia illustrates it nicely:
The SQL syntax for cartesian products is CROSS JOIN. For example:
SELECT *
-- This just generates all the days in January 2017
FROM generate_series(
'2017-01-01'::TIMESTAMP,
'2017-01-01'::TIMESTAMP + INTERVAL '1 month -1 day',
INTERVAL '1 day'
) AS days(day)
-- Here, we're combining all days with all departments
CROSS JOIN departments
Which combines all rows from one table with all rows from the other table:
Source:
+--------+ +------------+
| day | | department |
+--------+ +------------+
| Jan 01 | | Dept 1 |
| Jan 02 | | Dept 2 |
| ... | | Dept 3 |
| Jan 30 | +------------+
| Jan 31 |
+--------+
Result:
+--------+------------+
| day | department |
+--------+------------+
| Jan 01 | Dept 1 |
| Jan 01 | Dept 2 |
| Jan 01 | Dept 3 |
| Jan 02 | Dept 1 |
| Jan 02 | Dept 2 |
| Jan 02 | Dept 3 |
| ... | ... |
| Jan 31 | Dept 1 |
| Jan 31 | Dept 2 |
| Jan 31 | Dept 3 |
+--------+------------+
If we just write a comma separated list of tables, we'll get the same:
-- CROSS JOINing two tables:
SELECT * FROM table1, table2
INNER JOIN (Theta-JOIN)
An INNER JOIN is just a filtered CROSS JOIN where the filter predicate is called Theta in relational algebra.
For instance:
SELECT *
-- Same as before
FROM generate_series(
'2017-01-01'::TIMESTAMP,
'2017-01-01'::TIMESTAMP + INTERVAL '1 month -1 day',
INTERVAL '1 day'
) AS days(day)
-- Now, exclude all days/departments combinations for
-- days before the department was created
JOIN departments AS d ON day >= d.created_at
Note that the keyword INNER is optional (except in MS Access).
(look at the article for result examples)
EQUI JOIN
A special kind of Theta-JOIN is equi JOIN, which we use most. The predicate joins the primary key of one table with the foreign key of another table. If we use the Sakila database for illustration, we can write:
SELECT *
FROM actor AS a
JOIN film_actor AS fa ON a.actor_id = fa.actor_id
JOIN film AS f ON f.film_id = fa.film_id
This combines all actors with their films.
Or also, on some databases:
SELECT *
FROM actor
JOIN film_actor USING (actor_id)
JOIN film USING (film_id)
The USING() syntax allows for specifying a column that must be present on either side of a JOIN operation's tables and creates an equality predicate on those two columns.
NATURAL JOIN
Other answers have listed this "JOIN type" separately, but that doesn't make sense. It's just a syntax sugar form for equi JOIN, which is a special case of Theta-JOIN or INNER JOIN. NATURAL JOIN simply collects all columns that are common to both tables being joined and joins USING() those columns. Which is hardly ever useful, because of accidental matches (like LAST_UPDATE columns in the Sakila database).
Here's the syntax:
SELECT *
FROM actor
NATURAL JOIN film_actor
NATURAL JOIN film
OUTER JOIN
Now, OUTER JOIN is a bit different from INNER JOIN as it creates a UNION of several cartesian products. We can write:
-- Convenient syntax:
SELECT *
FROM a LEFT JOIN b ON <predicate>
-- Cumbersome, equivalent syntax:
SELECT a.*, b.*
FROM a JOIN b ON <predicate>
UNION ALL
SELECT a.*, NULL, NULL, ..., NULL
FROM a
WHERE NOT EXISTS (
SELECT * FROM b WHERE <predicate>
)
No one wants to write the latter, so we write OUTER JOIN (which is usually better optimised by databases).
Like INNER, the keyword OUTER is optional, here.
OUTER JOIN comes in three flavours:
LEFT [ OUTER ] JOIN: The left table of the JOIN expression is added to the union as shown above.
RIGHT [ OUTER ] JOIN: The right table of the JOIN expression is added to the union as shown above.
FULL [ OUTER ] JOIN: Both tables of the JOIN expression are added to the union as shown above.
All of these can be combined with the keyword USING() or with NATURAL (I've actually had a real world use-case for a NATURAL FULL JOIN recently)
Alternative syntaxes
There are some historic, deprecated syntaxes in Oracle and SQL Server, which supported OUTER JOIN already before the SQL standard had a syntax for this:
-- Oracle
SELECT *
FROM actor a, film_actor fa, film f
WHERE a.actor_id = fa.actor_id(+)
AND fa.film_id = f.film_id(+)
-- SQL Server
SELECT *
FROM actor a, film_actor fa, film f
WHERE a.actor_id *= fa.actor_id
AND fa.film_id *= f.film_id
Having said so, don't use this syntax. I just list this here so you can recognise it from old blog posts / legacy code.
Partitioned OUTER JOIN
Few people know this, but the SQL standard specifies partitioned OUTER JOIN (and Oracle implements it). You can write things like this:
WITH
-- Using CONNECT BY to generate all dates in January
days(day) AS (
SELECT DATE '2017-01-01' + LEVEL - 1
FROM dual
CONNECT BY LEVEL <= 31
),
-- Our departments
departments(department, created_at) AS (
SELECT 'Dept 1', DATE '2017-01-10' FROM dual UNION ALL
SELECT 'Dept 2', DATE '2017-01-11' FROM dual UNION ALL
SELECT 'Dept 3', DATE '2017-01-12' FROM dual UNION ALL
SELECT 'Dept 4', DATE '2017-04-01' FROM dual UNION ALL
SELECT 'Dept 5', DATE '2017-04-02' FROM dual
)
SELECT *
FROM days
LEFT JOIN departments
PARTITION BY (department) -- This is where the magic happens
ON day >= created_at
Parts of the result:
+--------+------------+------------+
| day | department | created_at |
+--------+------------+------------+
| Jan 01 | Dept 1 | | -- Didn't match, but still get row
| Jan 02 | Dept 1 | | -- Didn't match, but still get row
| ... | Dept 1 | | -- Didn't match, but still get row
| Jan 09 | Dept 1 | | -- Didn't match, but still get row
| Jan 10 | Dept 1 | Jan 10 | -- Matches, so get join result
| Jan 11 | Dept 1 | Jan 10 | -- Matches, so get join result
| Jan 12 | Dept 1 | Jan 10 | -- Matches, so get join result
| ... | Dept 1 | Jan 10 | -- Matches, so get join result
| Jan 31 | Dept 1 | Jan 10 | -- Matches, so get join result
The point here is that all rows from the partitioned side of the join will wind up in the result regardless if the JOIN matched anything on the "other side of the JOIN". Long story short: This is to fill up sparse data in reports. Very useful!
SEMI JOIN
Seriously? No other answer got this? Of course not, because it doesn't have a native syntax in SQL, unfortunately (just like ANTI JOIN below). But we can use IN() and EXISTS(), e.g. to find all actors who have played in films:
SELECT *
FROM actor a
WHERE EXISTS (
SELECT * FROM film_actor fa
WHERE a.actor_id = fa.actor_id
)
The WHERE a.actor_id = fa.actor_id predicate acts as the semi join predicate. If you don't believe it, check out execution plans, e.g. in Oracle. You'll see that the database executes a SEMI JOIN operation, not the EXISTS() predicate.
ANTI JOIN
This is just the opposite of SEMI JOIN (be careful not to use NOT IN though, as it has an important caveat)
Here are all the actors without films:
SELECT *
FROM actor a
WHERE NOT EXISTS (
SELECT * FROM film_actor fa
WHERE a.actor_id = fa.actor_id
)
Some folks (especially MySQL people) also write ANTI JOIN like this:
SELECT *
FROM actor a
LEFT JOIN film_actor fa
USING (actor_id)
WHERE film_id IS NULL
I think the historic reason is performance.
LATERAL JOIN
OMG, this one is too cool. I'm the only one to mention it? Here's a cool query:
SELECT a.first_name, a.last_name, f.*
FROM actor AS a
LEFT OUTER JOIN LATERAL (
SELECT f.title, SUM(amount) AS revenue
FROM film AS f
JOIN film_actor AS fa USING (film_id)
JOIN inventory AS i USING (film_id)
JOIN rental AS r USING (inventory_id)
JOIN payment AS p USING (rental_id)
WHERE fa.actor_id = a.actor_id -- JOIN predicate with the outer query!
GROUP BY f.film_id
ORDER BY revenue DESC
LIMIT 5
) AS f
ON true
It will find the TOP 5 revenue producing films per actor. Every time you need a TOP-N-per-something query, LATERAL JOIN will be your friend. If you're a SQL Server person, then you know this JOIN type under the name APPLY
SELECT a.first_name, a.last_name, f.*
FROM actor AS a
OUTER APPLY (
SELECT f.title, SUM(amount) AS revenue
FROM film AS f
JOIN film_actor AS fa ON f.film_id = fa.film_id
JOIN inventory AS i ON f.film_id = i.film_id
JOIN rental AS r ON i.inventory_id = r.inventory_id
JOIN payment AS p ON r.rental_id = p.rental_id
WHERE fa.actor_id = a.actor_id -- JOIN predicate with the outer query!
GROUP BY f.film_id
ORDER BY revenue DESC
LIMIT 5
) AS f
OK, perhaps that's cheating, because a LATERAL JOIN or APPLY expression is really a "correlated subquery" that produces several rows. But if we allow for "correlated subqueries", we can also talk about...
MULTISET
This is only really implemented by Oracle and Informix (to my knowledge), but it can be emulated in PostgreSQL using arrays and/or XML and in SQL Server using XML.
MULTISET produces a correlated subquery and nests the resulting set of rows in the outer query. The below query selects all actors and for each actor collects their films in a nested collection:
SELECT a.*, MULTISET (
SELECT f.*
FROM film AS f
JOIN film_actor AS fa USING (film_id)
WHERE a.actor_id = fa.actor_id
) AS films
FROM actor
As you have seen, there are more types of JOIN than just the "boring" INNER, OUTER, and CROSS JOIN that are usually mentioned. More details in my article. And please, stop using Venn diagrams to illustrate them.
I have created an illustration that explains better than words, in my opinion:
I'm going to push my pet peeve: the USING keyword.
If both tables on both sides of the JOIN have their foreign keys properly named (ie, same name, not just "id) then this can be used:
SELECT ...
FROM customers JOIN orders USING (customer_id)
I find this very practical, readable, and not used often enough.

Full outer join not bringing all results SQL-Server

I have an issue trying to retrieve all results from a join. I have set up a similar scenario in SQL fiddle and it works but in SQL Server it doesn't. I want to bring results for everything if they're either invoiced or shipped.
The result i am getting in SQL-SERVER is
| No | Order1 | Shipdate | No | Order1 | InvDate |
|-----|--------|----------|--------|--------|----------|
| 111 | 222 | 17-01-18 | 111 | 222 | 24-01-18 |
| 222 | 333 | 18-01-18 | 222 | 333 | 24-01-18 |
Even if the change the join to full outer, right join i still get this result.
I would have thought if i use full outer it will bring all the results back regardless of matches but it doesnt.
What am i missing to give me the full outer result? Thanks
sql fiddle - http://sqlfiddle.com/#!18/89943/1
This is your query:
SELECT S.No, s.Order1, s.Shipdate, i.No, i.Order1, i.InvDate
FROM Ship S LEFT JOIN
Invoice I
ON s.No=i.No AND s.Order1 = i.Order1
WHERE S.Person = 1;
Changing the LEFT JOIN to FULL JOIN doesn't change anything. The WHERE clause turns the FULL JOIN into a LEFT JOIN, because non-matching rows on that table have NULL values and fail the WHERE condition.
The OUTER JOIN query can be setup as follows:
SELECT
S.No, s.Order1, s.Shipdate,
i.No, i.Order1, i.InvDate
FROM Ship S
FULL JOIN Invoice I
ON s.No = i.No AND
s.Order1=i.Order1
-- WHERE S.Person = 1
and produces output
But by adding following filtering criteria to WHERE clause, the OUTER JOIN will produce exactly the same result with LEFT OUTER JOIN
WHERE S.Person = 1
Left Join
SELECT
S.No, s.Order1, s.Shipdate,
i.No, i.Order1, i.InvDate
FROM Ship S
LEFT JOIN Invoice I
ON s.No = i.No AND
s.Order1=i.Order1
WHERE S.Person = 1
In this sense, the Full Outer Join will give any rows that meet the ON clause criteria (S.[No]=I.[No] AND S.Order1=I.Order1) then any rows that don't meet the ON clause criteria but do meet the WHERE criteria.
So it is necessary to include WHERE I.Person=1 as well as WHERE S.Person=1 but qualified by the OR Clause for those rows that have not been shipped yet or have been shipped but not invoiced (if any).
SELECT S.[No],S.Order1,S.Shipdate,I.No,I.Order1,I.InvDate
FROM Ship S FULL OUTER JOIN Invoice I
ON S.[No]=I.[No] AND S.Order1=I.Order1
WHERE S.Person=1 OR I.Person=1
I am assuming you are looking only for Person 1's data.
You can use cross join to get the result for this.
Code
SELECT S.No, s.Order1, s.Shipdate, i.No, i.Order1, i.InvDate
FROM Ship S CROSS JOIN
Invoice I
WHERE S.Person = 1;

SQL include entries with no data

Here is my sql statement in Oracle that I am working with:
SELECT FACILITY.fac_name
, SUM(FEE_LOG.fee_amount) AS TOTAL_FEES
FROM FACILITY
, BOOK_DETAIL
, TRANS_LOG
, FEE_LOG
, TRANS_TYPE
WHERE
FACILITY.fac_id = BOOK_DETAIL.fac_id
AND BOOK_DETAIL.bkdt_id = TRANS_LOG.bkdt_id
AND TRANS_LOG.trans_id = FEE_LOG.trans_id
AND TRANS_LOG.trans_type_id = TRANS_TYPE.trans_type_id
AND
(
TRANS_TYPE.trans_type_desc = 'LOST'
OR TRANS_TYPE.trans_type_desc = 'CHECKIN'
)
GROUP BY FACILITY.fac_name;
It outputs something similar to this:
FACILITY TOTAL_FEES
Facility 1 8.45
Facility 2 4.23
Facility 3 5.23
I have 2 other facilities but they do not have any fees associated with them. I want to show them as 0
So the output would be like:
FACILITY TOTAL_FEES
Facility 1 8.45
Facility 2 4.23
Facility 3 5.23
Facility 4 0
Facility 5 0
ER Diagram
Use LEFT JOIN instead of implicit INNER JOIN for the FEE_LOG table
SELECT FACILITY.fac_name
, SUM(FEE_LOG.fee_amount) AS TOTAL_FEES
FROM FACILITY
JOIN BOOK_DETAIL ON FACILITY.fac_id = BOOK_DETAIL.fac_id
JOIN TRANS_LOG ON BOOK_DETAIL.bkdt_id = TRANS_LOG.bkdt_id
LEFT JOIN FEE_LOG ON TRANS_LOG.trans_id = FEE_LOG.trans_id
JOIN TRANS_TYPE TRANS_LOG.trans_type_id = TRANS_TYPE.trans_type_id
WHERE TRANS_TYPE.trans_type_desc IN ('LOST', 'CHECKIN')
GROUP BY FACILITY.fac_name;
Use outer joins and the on clause:
SELECT FACILITY.fac_name, SUM(nvl(FEE_LOG.fee_amount,0)) AS TOTAL_FEES
FROM FACILITY
left join BOOK_DETAIL
on FACILITY.fac_id = BOOK_DETAIL.fac_id
left join TRANS_LOG
on BOOK_DETAIL.bkdt_id = TRANS_LOG.bkdt_id
left join FEE_LOG
on TRANS_LOG.trans_id = FEE_LOG.trans_id
left join TRANS_TYPE
on TRANS_LOG.trans_type_id = TRANS_TYPE.trans_type_id
and TRANS_TYPE.trans_type_desc in ('LOST', 'CHECKIN')
GROUP BY FACILITY.fac_name;
Note: If these facilities you are referring to, that do not have any fees, have rows on BOOK_DETAIL or TRANS_LOG you can replace the outer join with an inner join (for just those tables). Any table at which point there may or may not be a related record you have to use an outer join.
Try this:
SELECT f.fac_name
, coalesce(SUM(fl.fee_amount),0) AS TOTAL_FEES
FROM FACILITY AS f
INNER JOIN BOOK_DETAIL AS bd
ON bd.fac_id = f.fac_id
INNER JOIN TRANS_LOG AS tl
ON tl.bkdt_id = bd.bkdt_id
LEFT OUTER JOIN FEE_LOG AS fl
ON fl.trans_id = tl.trans_id
INNER JOIN TRANS_TYPE AS tt
ON tt.trans_type_id = tl.trans_type_id
WHERE tt.trans_type_desc in ('LOST' , 'CHECKIN')
GROUP BY f.fac_name;
NB: when you list tables after from with commas between them you're effectively using a cross join.
When you add a condition to your where statement matching a field from one table to a field from another, the join becomes an inner join.
To select all records from one table along with any matches which may or may not exist from another you need an outer join.
There are 3 types:
left outer join where you want all records from the first table listed and any matching records from the second.
right outer join for all records from the second with only matches from the first.
full outer join is all records from both tables, alongside one another where there's a match.
You should always specify the type of join rather than implying it through where clauses / commas, as this makes your intentions clearer and thus your code more readable.

SQL JOIN and different types of JOINs

What is a SQL JOIN and what are different types?
An illustration from W3schools:
What is SQL JOIN ?
SQL JOIN is a method to retrieve data from two or more database tables.
What are the different SQL JOINs ?
There are a total of five JOINs. They are :
1. JOIN or INNER JOIN
2. OUTER JOIN
2.1 LEFT OUTER JOIN or LEFT JOIN
2.2 RIGHT OUTER JOIN or RIGHT JOIN
2.3 FULL OUTER JOIN or FULL JOIN
3. NATURAL JOIN
4. CROSS JOIN
5. SELF JOIN
1. JOIN or INNER JOIN :
In this kind of a JOIN, we get all records that match the condition in both tables, and records in both tables that do not match are not reported.
In other words, INNER JOIN is based on the single fact that: ONLY the matching entries in BOTH the tables SHOULD be listed.
Note that a JOIN without any other JOIN keywords (like INNER, OUTER, LEFT, etc) is an INNER JOIN. In other words, JOIN is
a Syntactic sugar for INNER JOIN (see: Difference between JOIN and INNER JOIN).
2. OUTER JOIN :
OUTER JOIN retrieves
Either,
the matched rows from one table and all rows in the other table
Or,
all rows in all tables (it doesn't matter whether or not there is a match).
There are three kinds of Outer Join :
2.1 LEFT OUTER JOIN or LEFT JOIN
This join returns all the rows from the left table in conjunction with the matching rows from the
right table. If there are no columns matching in the right table, it returns NULL values.
2.2 RIGHT OUTER JOIN or RIGHT JOIN
This JOIN returns all the rows from the right table in conjunction with the matching rows from the
left table. If there are no columns matching in the left table, it returns NULL values.
2.3 FULL OUTER JOIN or FULL JOIN
This JOIN combines LEFT OUTER JOIN and RIGHT OUTER JOIN. It returns rows from either table when the conditions are met and returns NULL value when there is no match.
In other words, OUTER JOIN is based on the fact that: ONLY the matching entries in ONE OF the tables (RIGHT or LEFT) or BOTH of the tables(FULL) SHOULD be listed.
Note that `OUTER JOIN` is a loosened form of `INNER JOIN`.
3. NATURAL JOIN :
It is based on the two conditions :
the JOIN is made on all the columns with the same name for equality.
Removes duplicate columns from the result.
This seems to be more of theoretical in nature and as a result (probably) most DBMS
don't even bother supporting this.
4. CROSS JOIN :
It is the Cartesian product of the two tables involved. The result of a CROSS JOIN will not make sense
in most of the situations. Moreover, we won't need this at all (or needs the least, to be precise).
5. SELF JOIN :
It is not a different form of JOIN, rather it is a JOIN (INNER, OUTER, etc) of a table to itself.
JOINs based on Operators
Depending on the operator used for a JOIN clause, there can be two types of JOINs. They are
Equi JOIN
Theta JOIN
1. Equi JOIN :
For whatever JOIN type (INNER, OUTER, etc), if we use ONLY the equality operator (=), then we say that
the JOIN is an EQUI JOIN.
2. Theta JOIN :
This is same as EQUI JOIN but it allows all other operators like >, <, >= etc.
Many consider both EQUI JOIN and Theta JOIN similar to INNER, OUTER
etc JOINs. But I strongly believe that its a mistake and makes the
ideas vague. Because INNER JOIN, OUTER JOIN etc are all connected with
the tables and their data whereas EQUI JOIN and THETA JOIN are only
connected with the operators we use in the former.
Again, there are many who consider NATURAL JOIN as some sort of
"peculiar" EQUI JOIN. In fact, it is true, because of the first
condition I mentioned for NATURAL JOIN. However, we don't have to
restrict that simply to NATURAL JOINs alone. INNER JOINs, OUTER JOINs
etc could be an EQUI JOIN too.
Definition:
JOINS are way to query the data that combined together from multiple tables simultaneously.
Types of JOINS:
Concern to RDBMS there are 5-types of joins:
Equi-Join: Combines common records from two tables based on equality condition.
Technically, Join made by using equality-operator (=) to compare values of Primary Key of one table and Foreign Key values of another table, hence result set includes common(matched) records from both tables. For implementation see INNER-JOIN.
Natural-Join: It is enhanced version of Equi-Join, in which SELECT
operation omits duplicate column. For implementation see INNER-JOIN
Non-Equi-Join: It is reverse of Equi-join where joining condition is uses other than equal operator(=) e.g, !=, <=, >=, >, < or BETWEEN etc. For implementation see INNER-JOIN.
Self-Join:: A customized behavior of join where a table combined with itself; This is typically needed for querying self-referencing tables (or Unary relationship entity).
For implementation see INNER-JOINs.
Cartesian Product: It cross combines all records of both tables without any condition. Technically, it returns the result set of a query without WHERE-Clause.
As per SQL concern and advancement, there are 3-types of joins and all RDBMS joins can be achieved using these types of joins.
INNER-JOIN: It merges(or combines) matched rows from two tables. The matching is done based on common columns of tables and their comparing operation. If equality based condition then: EQUI-JOIN performed, otherwise Non-EQUI-Join.
OUTER-JOIN: It merges(or combines) matched rows from two tables and unmatched rows with NULL values. However, can customized selection of un-matched rows e.g, selecting unmatched row from first table or second table by sub-types: LEFT OUTER JOIN and RIGHT OUTER JOIN.
2.1. LEFT Outer JOIN (a.k.a, LEFT-JOIN): Returns matched rows from two tables and unmatched from the LEFT table(i.e, first table) only.
2.2. RIGHT Outer JOIN (a.k.a, RIGHT-JOIN): Returns matched rows from two tables and unmatched from the RIGHT table only.
2.3. FULL OUTER JOIN (a.k.a OUTER JOIN): Returns matched and unmatched from both tables.
CROSS-JOIN: This join does not merges/combines instead it performs Cartesian product.
Note: Self-JOIN can be achieved by either INNER-JOIN, OUTER-JOIN and CROSS-JOIN based on requirement but the table must join with itself.
For more information:
Examples:
1.1: INNER-JOIN: Equi-join implementation
SELECT *
FROM Table1 A
INNER JOIN Table2 B ON A.<Primary-Key> =B.<Foreign-Key>;
1.2: INNER-JOIN: Natural-JOIN implementation
Select A.*, B.Col1, B.Col2 --But no B.ForeignKeyColumn in Select
FROM Table1 A
INNER JOIN Table2 B On A.Pk = B.Fk;
1.3: INNER-JOIN with NON-Equi-join implementation
Select *
FROM Table1 A INNER JOIN Table2 B On A.Pk <= B.Fk;
1.4: INNER-JOIN with SELF-JOIN
Select *
FROM Table1 A1 INNER JOIN Table1 A2 On A1.Pk = A2.Fk;
2.1: OUTER JOIN (full outer join)
Select *
FROM Table1 A FULL OUTER JOIN Table2 B On A.Pk = B.Fk;
2.2: LEFT JOIN
Select *
FROM Table1 A LEFT OUTER JOIN Table2 B On A.Pk = B.Fk;
2.3: RIGHT JOIN
Select *
FROM Table1 A RIGHT OUTER JOIN Table2 B On A.Pk = B.Fk;
3.1: CROSS JOIN
Select *
FROM TableA CROSS JOIN TableB;
3.2: CROSS JOIN-Self JOIN
Select *
FROM Table1 A1 CROSS JOIN Table1 A2;
//OR//
Select *
FROM Table1 A1,Table1 A2;
Interestingly most other answers suffer from these two problems:
They focus on basic forms of join only
They (ab)use Venn diagrams, which are an inaccurate tool for visualising joins (they're much better for unions).
I've recently written an article on the topic: A Probably Incomplete, Comprehensive Guide to the Many Different Ways to JOIN Tables in SQL, which I'll summarise here.
First and foremost: JOINs are cartesian products
This is why Venn diagrams explain them so inaccurately, because a JOIN creates a cartesian product between the two joined tables. Wikipedia illustrates it nicely:
The SQL syntax for cartesian products is CROSS JOIN. For example:
SELECT *
-- This just generates all the days in January 2017
FROM generate_series(
'2017-01-01'::TIMESTAMP,
'2017-01-01'::TIMESTAMP + INTERVAL '1 month -1 day',
INTERVAL '1 day'
) AS days(day)
-- Here, we're combining all days with all departments
CROSS JOIN departments
Which combines all rows from one table with all rows from the other table:
Source:
+--------+ +------------+
| day | | department |
+--------+ +------------+
| Jan 01 | | Dept 1 |
| Jan 02 | | Dept 2 |
| ... | | Dept 3 |
| Jan 30 | +------------+
| Jan 31 |
+--------+
Result:
+--------+------------+
| day | department |
+--------+------------+
| Jan 01 | Dept 1 |
| Jan 01 | Dept 2 |
| Jan 01 | Dept 3 |
| Jan 02 | Dept 1 |
| Jan 02 | Dept 2 |
| Jan 02 | Dept 3 |
| ... | ... |
| Jan 31 | Dept 1 |
| Jan 31 | Dept 2 |
| Jan 31 | Dept 3 |
+--------+------------+
If we just write a comma separated list of tables, we'll get the same:
-- CROSS JOINing two tables:
SELECT * FROM table1, table2
INNER JOIN (Theta-JOIN)
An INNER JOIN is just a filtered CROSS JOIN where the filter predicate is called Theta in relational algebra.
For instance:
SELECT *
-- Same as before
FROM generate_series(
'2017-01-01'::TIMESTAMP,
'2017-01-01'::TIMESTAMP + INTERVAL '1 month -1 day',
INTERVAL '1 day'
) AS days(day)
-- Now, exclude all days/departments combinations for
-- days before the department was created
JOIN departments AS d ON day >= d.created_at
Note that the keyword INNER is optional (except in MS Access).
(look at the article for result examples)
EQUI JOIN
A special kind of Theta-JOIN is equi JOIN, which we use most. The predicate joins the primary key of one table with the foreign key of another table. If we use the Sakila database for illustration, we can write:
SELECT *
FROM actor AS a
JOIN film_actor AS fa ON a.actor_id = fa.actor_id
JOIN film AS f ON f.film_id = fa.film_id
This combines all actors with their films.
Or also, on some databases:
SELECT *
FROM actor
JOIN film_actor USING (actor_id)
JOIN film USING (film_id)
The USING() syntax allows for specifying a column that must be present on either side of a JOIN operation's tables and creates an equality predicate on those two columns.
NATURAL JOIN
Other answers have listed this "JOIN type" separately, but that doesn't make sense. It's just a syntax sugar form for equi JOIN, which is a special case of Theta-JOIN or INNER JOIN. NATURAL JOIN simply collects all columns that are common to both tables being joined and joins USING() those columns. Which is hardly ever useful, because of accidental matches (like LAST_UPDATE columns in the Sakila database).
Here's the syntax:
SELECT *
FROM actor
NATURAL JOIN film_actor
NATURAL JOIN film
OUTER JOIN
Now, OUTER JOIN is a bit different from INNER JOIN as it creates a UNION of several cartesian products. We can write:
-- Convenient syntax:
SELECT *
FROM a LEFT JOIN b ON <predicate>
-- Cumbersome, equivalent syntax:
SELECT a.*, b.*
FROM a JOIN b ON <predicate>
UNION ALL
SELECT a.*, NULL, NULL, ..., NULL
FROM a
WHERE NOT EXISTS (
SELECT * FROM b WHERE <predicate>
)
No one wants to write the latter, so we write OUTER JOIN (which is usually better optimised by databases).
Like INNER, the keyword OUTER is optional, here.
OUTER JOIN comes in three flavours:
LEFT [ OUTER ] JOIN: The left table of the JOIN expression is added to the union as shown above.
RIGHT [ OUTER ] JOIN: The right table of the JOIN expression is added to the union as shown above.
FULL [ OUTER ] JOIN: Both tables of the JOIN expression are added to the union as shown above.
All of these can be combined with the keyword USING() or with NATURAL (I've actually had a real world use-case for a NATURAL FULL JOIN recently)
Alternative syntaxes
There are some historic, deprecated syntaxes in Oracle and SQL Server, which supported OUTER JOIN already before the SQL standard had a syntax for this:
-- Oracle
SELECT *
FROM actor a, film_actor fa, film f
WHERE a.actor_id = fa.actor_id(+)
AND fa.film_id = f.film_id(+)
-- SQL Server
SELECT *
FROM actor a, film_actor fa, film f
WHERE a.actor_id *= fa.actor_id
AND fa.film_id *= f.film_id
Having said so, don't use this syntax. I just list this here so you can recognise it from old blog posts / legacy code.
Partitioned OUTER JOIN
Few people know this, but the SQL standard specifies partitioned OUTER JOIN (and Oracle implements it). You can write things like this:
WITH
-- Using CONNECT BY to generate all dates in January
days(day) AS (
SELECT DATE '2017-01-01' + LEVEL - 1
FROM dual
CONNECT BY LEVEL <= 31
),
-- Our departments
departments(department, created_at) AS (
SELECT 'Dept 1', DATE '2017-01-10' FROM dual UNION ALL
SELECT 'Dept 2', DATE '2017-01-11' FROM dual UNION ALL
SELECT 'Dept 3', DATE '2017-01-12' FROM dual UNION ALL
SELECT 'Dept 4', DATE '2017-04-01' FROM dual UNION ALL
SELECT 'Dept 5', DATE '2017-04-02' FROM dual
)
SELECT *
FROM days
LEFT JOIN departments
PARTITION BY (department) -- This is where the magic happens
ON day >= created_at
Parts of the result:
+--------+------------+------------+
| day | department | created_at |
+--------+------------+------------+
| Jan 01 | Dept 1 | | -- Didn't match, but still get row
| Jan 02 | Dept 1 | | -- Didn't match, but still get row
| ... | Dept 1 | | -- Didn't match, but still get row
| Jan 09 | Dept 1 | | -- Didn't match, but still get row
| Jan 10 | Dept 1 | Jan 10 | -- Matches, so get join result
| Jan 11 | Dept 1 | Jan 10 | -- Matches, so get join result
| Jan 12 | Dept 1 | Jan 10 | -- Matches, so get join result
| ... | Dept 1 | Jan 10 | -- Matches, so get join result
| Jan 31 | Dept 1 | Jan 10 | -- Matches, so get join result
The point here is that all rows from the partitioned side of the join will wind up in the result regardless if the JOIN matched anything on the "other side of the JOIN". Long story short: This is to fill up sparse data in reports. Very useful!
SEMI JOIN
Seriously? No other answer got this? Of course not, because it doesn't have a native syntax in SQL, unfortunately (just like ANTI JOIN below). But we can use IN() and EXISTS(), e.g. to find all actors who have played in films:
SELECT *
FROM actor a
WHERE EXISTS (
SELECT * FROM film_actor fa
WHERE a.actor_id = fa.actor_id
)
The WHERE a.actor_id = fa.actor_id predicate acts as the semi join predicate. If you don't believe it, check out execution plans, e.g. in Oracle. You'll see that the database executes a SEMI JOIN operation, not the EXISTS() predicate.
ANTI JOIN
This is just the opposite of SEMI JOIN (be careful not to use NOT IN though, as it has an important caveat)
Here are all the actors without films:
SELECT *
FROM actor a
WHERE NOT EXISTS (
SELECT * FROM film_actor fa
WHERE a.actor_id = fa.actor_id
)
Some folks (especially MySQL people) also write ANTI JOIN like this:
SELECT *
FROM actor a
LEFT JOIN film_actor fa
USING (actor_id)
WHERE film_id IS NULL
I think the historic reason is performance.
LATERAL JOIN
OMG, this one is too cool. I'm the only one to mention it? Here's a cool query:
SELECT a.first_name, a.last_name, f.*
FROM actor AS a
LEFT OUTER JOIN LATERAL (
SELECT f.title, SUM(amount) AS revenue
FROM film AS f
JOIN film_actor AS fa USING (film_id)
JOIN inventory AS i USING (film_id)
JOIN rental AS r USING (inventory_id)
JOIN payment AS p USING (rental_id)
WHERE fa.actor_id = a.actor_id -- JOIN predicate with the outer query!
GROUP BY f.film_id
ORDER BY revenue DESC
LIMIT 5
) AS f
ON true
It will find the TOP 5 revenue producing films per actor. Every time you need a TOP-N-per-something query, LATERAL JOIN will be your friend. If you're a SQL Server person, then you know this JOIN type under the name APPLY
SELECT a.first_name, a.last_name, f.*
FROM actor AS a
OUTER APPLY (
SELECT f.title, SUM(amount) AS revenue
FROM film AS f
JOIN film_actor AS fa ON f.film_id = fa.film_id
JOIN inventory AS i ON f.film_id = i.film_id
JOIN rental AS r ON i.inventory_id = r.inventory_id
JOIN payment AS p ON r.rental_id = p.rental_id
WHERE fa.actor_id = a.actor_id -- JOIN predicate with the outer query!
GROUP BY f.film_id
ORDER BY revenue DESC
LIMIT 5
) AS f
OK, perhaps that's cheating, because a LATERAL JOIN or APPLY expression is really a "correlated subquery" that produces several rows. But if we allow for "correlated subqueries", we can also talk about...
MULTISET
This is only really implemented by Oracle and Informix (to my knowledge), but it can be emulated in PostgreSQL using arrays and/or XML and in SQL Server using XML.
MULTISET produces a correlated subquery and nests the resulting set of rows in the outer query. The below query selects all actors and for each actor collects their films in a nested collection:
SELECT a.*, MULTISET (
SELECT f.*
FROM film AS f
JOIN film_actor AS fa USING (film_id)
WHERE a.actor_id = fa.actor_id
) AS films
FROM actor
As you have seen, there are more types of JOIN than just the "boring" INNER, OUTER, and CROSS JOIN that are usually mentioned. More details in my article. And please, stop using Venn diagrams to illustrate them.
I have created an illustration that explains better than words, in my opinion:
I'm going to push my pet peeve: the USING keyword.
If both tables on both sides of the JOIN have their foreign keys properly named (ie, same name, not just "id) then this can be used:
SELECT ...
FROM customers JOIN orders USING (customer_id)
I find this very practical, readable, and not used often enough.

3 joins and where clause together

I have 3 tables
bl_main (bl_id UNIQUE, bl_area)
bl_details (bl_id UNIQUE, name)
bl_data(bl_id, month, paper_tons, bottles_tons)
bl_id is not unique in the last table. There will be multiple rows of same bl_id.
I am trying to retrieve data in the following way
bl_id | name | bl_area | sum(paper_tons) | sum (bottles_tons) | paper_tons | bottles_tons
sum(paper_tons) should return the sum of all the paper tons for the same bl_id like Jan to December.
Using the below query i am able to retrieve all the data correctly except in the result, there are multiple occurances of bl_ids(From bl_data table).
SELECT bl_main.bl_id,name,bl_area,sums.SummedPaper, sums.SummedBottles,paper_tons,bottles_tons
FROM bl_main
JOIN bl_details ON
bl_main.bl_id= bl_details.bl_id
left outer JOIN bl_data ON
bl_data.bl_id= bl_main.bl_id
left outer JOIN (
SELECT bl_id, SUM(Paper_tons) As SummedPaper, SUM(bottle_tons) As SummedBottles
FROM bl_data
GROUP by bl_id) sums ON sums.bl_id = bl_main.bl_id
I wanto retrieve only the unique values of bl_ids without repetition and it should contain the bl_id which has the max month and not all the months for the same bl_id.
For ex:
INCORRECT
**0601** University Hall 75.76 17051 1356 4040 1154 **11**
**0601** University Hall 75.76 17051 1356 9190 101 **12**
**0605** UIC Student 22.86 3331 14799 0 356 **8**
CORRECT
**0601** University Hall 75.76 17051 1356 9190 101 **12**
**0605** UIC Student 22.86 3331 14799 0 356 **8**
I know I can get the max value using
WHERE Month = (SELECT MAX(Month)
but where exactlt should i add this in the query and should i change the join definition.
Any help is highly appreciated as i am new to sql. Thanks in advance.
You have two tables that probably should be combined into one (bl_main and bl_details). But putting that aside, what you need is a self-join subquery to select the row with the max month. Something like the following (untested):
SELECT bl_main.bl_id, bl_details.name, bl_main.bl_area, sums.sum_paper_tons,
sums.sum_bottles_tons, maxmonth.paper_tons, maxmonth.bottles_tons
FROM bl_main
INNER JOIN bl_details ON bl_main.bl_id = bl_details.bl_id
LEFT OUTER JOIN (SELECT bl_id, SUM(paper_tons) AS sum_paper_tons,
SUM(bottles_tons) AS sum_bottles_tons
FROM bl_data
GROUP BY bl_id) sums ON bl_main.bl_id = sums.bl_id
LEFT OUTER JOIN (SELECT bl_id, paper_tons, bottles_tons
FROM bl_data data2
INNER JOIN (SELECT bl_id, MAX(month) AS max_month
FROM bl_data
GROUP BY bl_id) m
ON m.bl_id = data2.bl_id
AND m.max_month = data2.month) maxmonth
ON bl_main.bl_id = maxmonth.bl_id
You can join the table containing the month against itself, using a subquery of the form:
Select *
From mytable m
Inner Join (Select max(Month) as Month, myId
From mytable
Group By myId) mnth
On mnth.myId = m.myId and mnth.Month = m.Month
Your JOIN clause
left outer JOIN bl_data ON
bl_data.bl_id= bl_main.bl_id
does not specify which month to select for the data you are displaying with paper_tons and bottles_tons.
You could update that JOIN to only contain the max month, and this should limit the entries, like so:
left outer JOIN (SELECT bl_id, MAX(Month) as Month from bl_data GROUP BY bl_id) as Month
ON Month.bl_id = bl_main.bl_id
left outer JOIN bl_data ON
bl_data.bl_id = bl_main.bl_id AND bl_data.Month = Month.bl_Month
I think this query is what you are looking for
SELECT bl_main.bl_id,name, bl_area, sums.SummedPaper, sums.SummedBottles, paper_tons, bottles_tons
FROM bl_main
JOIN bl_details ON bl_main.bl_id= bl_details.bl_id
left outer JOIN bl_data ON bl_data.bl_id= bl_main.bl_id
left outer JOIN
(
SELECT bl_id, month, SUM(Paper_tons) As SummedPaper, SUM(bottle_tons) As SummedBottles
FROM bl_data
WHERE month in
(SELECT MAX(month) FROM bl_data GROUP BY bl_id)
GROUP BY bl_id, month
) sums ON sums.bl_id = bl_main.bl_id
I wanted to just add a comment to the answer lc gave, but I don't have 50 reputation points yet. It is a link to an article that I believe explains this question and adds the why the solution that lc gave is correct.
http://www.sqlteam.com/article/how-to-use-group-by-with-distinct-aggregates-and-derived-tables