UPDATE JOIN statement for DB2 - database

I am using DB2, and am a beginner in SQL. I have two tables here:
Table1:
ID | PageID
------------
1 | 101
2 | 102
3 | 103
4 | 104
Table2:
ID | SRCID | PageID
--------------------
1 | 2 | 179
2 | 3 | 103
3 | 3 | 109
Table2 and Table1 have different number of records. Table2.SCRID corresponds to Table1.ID.
I would like to update the PageID in Table2 to follow what is stated in PageID of Table1, based on the SRCID.
My end result of Table2 should be:
ID | SRCID | PageID
--------------------
1 | 2 | 102
2 | 3 | 103
3 | 3 | 103
How do I do this in SQL for DB2?
I tried:
UPDATE table2
SET PageID = (SELECT t1.PageID from table1 as t1 join table2 as t2
WHERE t2.SCRID = t1.ID);
But the above doesn't work as I get:
DB21034E The command was processed as an SQL statement because it was not a
valid Command Line Processor command. During SQL processing it returned:
SQL0811N The result of a scalar fullselect, SELECT INTO statement, or VALUES
INTO statement is more than one row. SQLSTATE=21000
The problem here is there is no unique column for me to join such that each column gets a unique result..or so it seems to me. Please help? :(

Try this:
UPDATE table2
SET table2.PageID =
(SELECT t1.PageID
FROM table1 t1
WHERE t1.id = table2.SCRID)
WHERE EXISTS(
SELECT 'TABLE1PAGE'
FROM table1 t1
WHERE t1.id = table2.SCRID)
I've added EXISTS clause to prevent NULL assignment to PageID of table2

As a SQL Server loyalist, I've been struggling with DB2's seeming inability to update a table with information from another table--the update with join that's so easy in SSMS.
I finally discovered a workaround that functions perfectly instead: the MERGE statement. I usually find IBM's support documents impenetrable, or at least not friendly reading, but the explanation at their MERGE website was actually quite clear: https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_71/sqlp/rbafymerge.htm
Hope this helps you as much as it did me.

Related

update column values from another table with different column name but same column value in MS SQL

update column values from another table with different column name but same column value
I have two tables as mentioned below :
Table1
ID | Name
1 | A
2 | A
3 | A
4 | A
Table2
IDX | Name
1 | XYZ
2 | PQR
3 | PPS
update Table1
set Name = (Select Name from Table2 where Table1.ID = Table2.IDX)
I'm getting below result after executing above query.
ID | Name
1 | XYZ
2 | PQR
3 | PPS
4 | NULL
But I need result as mentioned below:
ID | Name
1 | XYZ
2 | PQR
3 | PPS
4 | A
Can somebody help with this ? Thanks!
Using an update join we can try:
UPDATE t1
SET Name = t2.Name
FROM Table1 t1
INNER JOIN Table2 t2
ON t2.IDX = t1.ID;
Only records from Table1 which match to something in Table2 will be updated. This avoids the problem of making a null assignment from which your current approach suffers. You could make the following slight change to your current update to avoid the problem:
UPDATE Table1
SET Name = (SELECT COALESCE(t2.Name, Table1.Name) FROM Table2 t2
WHERE Table1.ID = t2.IDX);

SQL Server - performance for filtering using LEFT JOIN ON condition versus WHERE condition [duplicate]

After reading it, this is not a duplicate of Explicit vs Implicit SQL Joins.
The answer may be related (or even the same) but the question is different.
What is the difference and what should go in each?
If I understand the theory correctly, the query optimizer should be able to use both interchangeably.
They are not the same thing.
Consider these queries:
SELECT *
FROM Orders
LEFT JOIN OrderLines ON OrderLines.OrderID=Orders.ID
WHERE Orders.ID = 12345
and
SELECT *
FROM Orders
LEFT JOIN OrderLines ON OrderLines.OrderID=Orders.ID
AND Orders.ID = 12345
The first will return an order and its lines, if any, for order number 12345.
The second will return all orders, but only order 12345 will have any lines associated with it.
With an INNER JOIN, the clauses are effectively equivalent. However, just because they are functionally the same, in that they produce the same results, does not mean the two kinds of clauses have the same semantic meaning.
Does not matter for inner joins
Matters for outer joins
a. WHERE clause: After joining. Records will be filtered after join has taken place.
b. ON clause - Before joining. Records (from right table) will be filtered before joining. This may end up as null in the result (since OUTER join).
Example: Consider the below tables:
documents:
id
name
1
Document1
2
Document2
3
Document3
4
Document4
5
Document5
downloads:
id
document_id
username
1
1
sandeep
2
1
simi
3
2
sandeep
4
2
reya
5
3
simi
a) Inside WHERE clause:
SELECT documents.name, downloads.id
FROM documents
LEFT OUTER JOIN downloads
ON documents.id = downloads.document_id
WHERE username = 'sandeep'
For above query the intermediate join table will look like this.
id(from documents)
name
id (from downloads)
document_id
username
1
Document1
1
1
sandeep
1
Document1
2
1
simi
2
Document2
3
2
sandeep
2
Document2
4
2
reya
3
Document3
5
3
simi
4
Document4
NULL
NULL
NULL
5
Document5
NULL
NULL
NULL
After applying the WHERE clause and selecting the listed attributes, the result will be:
name
id
Document1
1
Document2
3
b) Inside JOIN clause
SELECT documents.name, downloads.id
FROM documents
LEFT OUTER JOIN downloads
ON documents.id = downloads.document_id
AND username = 'sandeep'
For above query the intermediate join table will look like this.
id(from documents)
name
id (from downloads)
document_id
username
1
Document1
1
1
sandeep
2
Document2
3
2
sandeep
3
Document3
NULL
NULL
NULL
4
Document4
NULL
NULL
NULL
5
Document5
NULL
NULL
NULL
Notice how the rows in documents that did not match both the conditions are populated with NULL values.
After Selecting the listed attributes, the result will be:
name
id
Document1
1
Document2
3
Document3
NULL
Document4
NULL
Document5
NULL
On INNER JOINs they are interchangeable, and the optimizer will rearrange them at will.
On OUTER JOINs, they are not necessarily interchangeable, depending on which side of the join they depend on.
I put them in either place depending on the readability.
The way I do it is:
Always put the join conditions in the ON clause if you are doing an INNER JOIN. So, do not add any WHERE conditions to the ON clause, put them in the WHERE clause.
If you are doing a LEFT JOIN, add any WHERE conditions to the ON clause for the table in the right side of the join. This is a must, because adding a WHERE clause that references the right side of the join will convert the join to an INNER JOIN.
The exception is when you are looking for the records that are not in a particular table. You would add the reference to a unique identifier (that is not ever NULL) in the RIGHT JOIN table to the WHERE clause this way: WHERE t2.idfield IS NULL. So, the only time you should reference a table on the right side of the join is to find those records which are not in the table.
On an inner join, they mean the same thing. However you will get different results in an outer join depending on if you put the join condition in the WHERE vs the ON clause. Take a look at this related question and this answer (by me).
I think it makes the most sense to be in the habit of always putting the join condition in the ON clause (unless it is an outer join and you actually do want it in the where clause) as it makes it clearer to anyone reading your query what conditions the tables are being joined on, and also it helps prevent the WHERE clause from being dozens of lines long.
Short answer
It depends on whether the JOIN type is INNER or OUTER.
For INNER JOIN the answer is yes since an INNER JOIN statement can be rewritten as a CROSS JOIN with a WHERE clause matching the same condition you used in the ON clause of the INNER JOIN query.
However, this only applies to INNER JOIN, not for OUTER JOIN.
Long answer
Considering we have the following post and post_comment tables:
The post has the following records:
| id | title |
|----|-----------|
| 1 | Java |
| 2 | Hibernate |
| 3 | JPA |
and the post_comment has the following three rows:
| id | review | post_id |
|----|-----------|---------|
| 1 | Good | 1 |
| 2 | Excellent | 1 |
| 3 | Awesome | 2 |
SQL INNER JOIN
The SQL JOIN clause allows you to associate rows that belong to different tables. For instance, a CROSS JOIN will create a Cartesian Product containing all possible combinations of rows between the two joining tables.
While the CROSS JOIN is useful in certain scenarios, most of the time, you want to join tables based on a specific condition. And, that's where INNER JOIN comes into play.
The SQL INNER JOIN allows us to filter the Cartesian Product of joining two tables based on a condition that is specified via the ON clause.
SQL INNER JOIN - ON "always true" condition
If you provide an "always true" condition, the INNER JOIN will not filter the joined records, and the result set will contain the Cartesian Product of the two joining tables.
For instance, if we execute the following SQL INNER JOIN query:
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
INNER JOIN post_comment pc ON 1 = 1
We will get all combinations of post and post_comment records:
| p.id | pc.id |
|---------|------------|
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
| 3 | 1 |
| 3 | 2 |
| 3 | 3 |
So, if the ON clause condition is "always true", the INNER JOIN is simply equivalent to a CROSS JOIN query:
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
CROSS JOIN post_comment
WHERE 1 = 1
ORDER BY p.id, pc.id
SQL INNER JOIN - ON "always false" condition
On the other hand, if the ON clause condition is "always false", then all the joined records are going to be filtered out and the result set will be empty.
So, if we execute the following SQL INNER JOIN query:
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
INNER JOIN post_comment pc ON 1 = 0
ORDER BY p.id, pc.id
We won't get any result back:
| p.id | pc.id |
|---------|------------|
That's because the query above is equivalent to the following CROSS JOIN query:
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
CROSS JOIN post_comment
WHERE 1 = 0
ORDER BY p.id, pc.id
SQL INNER JOIN - ON clause using the Foreign Key and Primary Key columns
The most common ON clause condition is the one that matches the Foreign Key column in the child table with the Primary Key column in the parent table, as illustrated by the following query:
SELECT
p.id AS "p.id",
pc.post_id AS "pc.post_id",
pc.id AS "pc.id",
p.title AS "p.title",
pc.review AS "pc.review"
FROM post p
INNER JOIN post_comment pc ON pc.post_id = p.id
ORDER BY p.id, pc.id
When executing the above SQL INNER JOIN query, we get the following result set:
| p.id | pc.post_id | pc.id | p.title | pc.review |
|---------|------------|------------|------------|-----------|
| 1 | 1 | 1 | Java | Good |
| 1 | 1 | 2 | Java | Excellent |
| 2 | 2 | 3 | Hibernate | Awesome |
So, only the records that match the ON clause condition are included in the query result set. In our case, the result set contains all the post along with their post_comment records. The post rows that have no associated post_comment are excluded since they can not satisfy the ON Clause condition.
Again, the above SQL INNER JOIN query is equivalent to the following CROSS JOIN query:
SELECT
p.id AS "p.id",
pc.post_id AS "pc.post_id",
pc.id AS "pc.id",
p.title AS "p.title",
pc.review AS "pc.review"
FROM post p, post_comment pc
WHERE pc.post_id = p.id
The non-struck rows are the ones that satisfy the WHERE clause, and only these records are going to be included in the result set. That's the best way to visualize how the INNER JOIN clause works.
| p.id | pc.post_id | pc.id | p.title | pc.review |
|------|------------|-------|-----------|-----------|
| 1 | 1 | 1 | Java | Good |
| 1 | 1 | 2 | Java | Excellent |
| 1 | 2 | 3 | Java | Awesome |
| 2 | 1 | 1 | Hibernate | Good |
| 2 | 1 | 2 | Hibernate | Excellent |
| 2 | 2 | 3 | Hibernate | Awesome |
| 3 | 1 | 1 | JPA | Good |
| 3 | 1 | 2 | JPA | Excellent |
| 3 | 2 | 3 | JPA | Awesome |
Conclusion
An INNER JOIN statement can be rewritten as a CROSS JOIN with a WHERE clause matching the same condition you used in the ON clause of the INNER JOIN query.
Not that this only applies to INNER JOIN, not for OUTER JOIN.
Let's consider those tables :
A
id | SomeData
B
id | id_A | SomeOtherData
id_A being a foreign key to table A
Writting this query :
SELECT *
FROM A
LEFT JOIN B
ON A.id = B.id_A;
Will provide this result :
/ : part of the result
B
+---------------------------------+
A | |
+---------------------+-------+ |
|/////////////////////|///////| |
|/////////////////////|///////| |
|/////////////////////|///////| |
|/////////////////////|///////| |
|/////////////////////+-------+-------------------------+
|/////////////////////////////|
+-----------------------------+
What is in A but not in B means that there is null values for B.
Now, let's consider a specific part in B.id_A, and highlight it from the previous result :
/ : part of the result
* : part of the result with the specific B.id_A
B
+---------------------------------+
A | |
+---------------------+-------+ |
|/////////////////////|///////| |
|/////////////////////|///////| |
|/////////////////////+---+///| |
|/////////////////////|***|///| |
|/////////////////////+---+---+-------------------------+
|/////////////////////////////|
+-----------------------------+
Writting this query :
SELECT *
FROM A
LEFT JOIN B
ON A.id = B.id_A
AND B.id_A = SpecificPart;
Will provide this result :
/ : part of the result
* : part of the result with the specific B.id_A
B
+---------------------------------+
A | |
+---------------------+-------+ |
|/////////////////////| | |
|/////////////////////| | |
|/////////////////////+---+ | |
|/////////////////////|***| | |
|/////////////////////+---+---+-------------------------+
|/////////////////////////////|
+-----------------------------+
Because this removes in the inner join the values that aren't in B.id_A = SpecificPart
Now, let's change the query to this :
SELECT *
FROM A
LEFT JOIN B
ON A.id = B.id_A
WHERE B.id_A = SpecificPart;
The result is now :
/ : part of the result
* : part of the result with the specific B.id_A
B
+---------------------------------+
A | |
+---------------------+-------+ |
| | | |
| | | |
| +---+ | |
| |***| | |
| +---+---+-------------------------+
| |
+-----------------------------+
Because the whole result is filtered against B.id_A = SpecificPart removing the parts B.id_A IS NULL, that are in the A that aren't in B
There is great difference between where clause vs. on clause, when it comes to left join.
Here is example:
mysql> desc t1;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | NO | | NULL | |
| fid | int(11) | NO | | NULL | |
| v | varchar(20) | NO | | NULL | |
+-------+-------------+------+-----+---------+-------+
There fid is id of table t2.
mysql> desc t2;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | NO | | NULL | |
| v | varchar(10) | NO | | NULL | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
Query on "on clause" :
mysql> SELECT * FROM `t1` left join t2 on fid = t2.id AND t1.v = 'K'
-> ;
+----+-----+---+------+------+
| id | fid | v | id | v |
+----+-----+---+------+------+
| 1 | 1 | H | NULL | NULL |
| 2 | 1 | B | NULL | NULL |
| 3 | 2 | H | NULL | NULL |
| 4 | 7 | K | NULL | NULL |
| 5 | 5 | L | NULL | NULL |
+----+-----+---+------+------+
5 rows in set (0.00 sec)
Query on "where clause":
mysql> SELECT * FROM `t1` left join t2 on fid = t2.id where t1.v = 'K';
+----+-----+---+------+------+
| id | fid | v | id | v |
+----+-----+---+------+------+
| 4 | 7 | K | NULL | NULL |
+----+-----+---+------+------+
1 row in set (0.00 sec)
It is clear that,
the first query returns a record from t1 and its dependent row from t2, if any, for row t1.v = 'K'.
The second query returns rows from t1, but only for t1.v = 'K' will have any associated row with it.
In terms of the optimizer, it shouldn't make a difference whether you define your join clauses with ON or WHERE.
However, IMHO, I think it's much clearer to use the ON clause when performing joins. That way you have a specific section of you query that dictates how the join is handled versus intermixed with the rest of the WHERE clauses.
Are you trying to join data or filter data?
For readability it makes the most sense to isolate these use cases to ON and WHERE respectively.
join data in ON
filter data in WHERE
It can become very difficult to read a query where the JOIN condition and a filtering condition exist in the WHERE clause.
Performance wise you should not see a difference, though different types of SQL sometimes handle query planning differently so it can be worth trying ¯\_(ツ)_/¯ (Do be aware of caching effecting the query speed)
Also as others have noted, if you use an outer join you will get different results if you place the filter condition in the ON clause because it only effects one of the tables.
I wrote a more in depth post about this here:
https://dataschool.com/learn/difference-between-where-and-on-in-sql
I think this distinction can best be explained via the logical order of operations in SQL, which is, simplified:
FROM (including joins)
WHERE
GROUP BY
Aggregations
HAVING
WINDOW
SELECT
DISTINCT
UNION, INTERSECT, EXCEPT
ORDER BY
OFFSET
FETCH
Joins are not a clause of the select statement, but an operator inside of FROM. As such, all ON clauses belonging to the corresponding JOIN operator have "already happened" logically by the time logical processing reaches the WHERE clause. This means that in the case of a LEFT JOIN, for example, the outer join's semantics has already happend by the time the WHERE clause is applied.
I've explained the following example more in depth in this blog post. When running this query:
SELECT a.actor_id, a.first_name, a.last_name, count(fa.film_id)
FROM actor a
LEFT JOIN film_actor fa ON a.actor_id = fa.actor_id
WHERE film_id < 10
GROUP BY a.actor_id, a.first_name, a.last_name
ORDER BY count(fa.film_id) ASC;
The LEFT JOIN doesn't really have any useful effect, because even if an actor did not play in a film, the actor will be filtered, as its FILM_ID will be NULL and the WHERE clause will filter such a row. The result is something like:
ACTOR_ID FIRST_NAME LAST_NAME COUNT
--------------------------------------
194 MERYL ALLEN 1
198 MARY KEITEL 1
30 SANDRA PECK 1
85 MINNIE ZELLWEGER 1
123 JULIANNE DENCH 1
I.e. just as if we inner joined the two tables. If we move the filter predicate in the ON clause, it now becomes a criteria for the outer join:
SELECT a.actor_id, a.first_name, a.last_name, count(fa.film_id)
FROM actor a
LEFT JOIN film_actor fa ON a.actor_id = fa.actor_id
AND film_id < 10
GROUP BY a.actor_id, a.first_name, a.last_name
ORDER BY count(fa.film_id) ASC;
Meaning the result will contain actors without any films, or without any films with FILM_ID < 10
ACTOR_ID FIRST_NAME LAST_NAME COUNT
-----------------------------------------
3 ED CHASE 0
4 JENNIFER DAVIS 0
5 JOHNNY LOLLOBRIGIDA 0
6 BETTE NICHOLSON 0
...
1 PENELOPE GUINESS 1
200 THORA TEMPLE 1
2 NICK WAHLBERG 1
198 MARY KEITEL 1
In short
Always put your predicate where it makes most sense, logically.
In SQL, the 'WHERE' and 'ON' clause,are kind of Conditional Statemants, but the major difference between them are, the 'Where' Clause is used in Select/Update Statements for specifying the Conditions, whereas the 'ON' Clause is used in Joins, where it verifies or checks if the Records are Matched in the target and source tables, before the Tables are Joined
For Example: - 'WHERE'
SELECT * FROM employee WHERE employee_id=101
For Example: - 'ON'
There are two tables employee and employee_details, the matching columns are employee_id.
SELECT * FROM employee
INNER JOIN employee_details
ON employee.employee_id = employee_details.employee_id
Hope I have answered your Question.
Revert for any clarifications.
I think it's the join sequence effect.
In the upper left join case, SQL do Left join first and then do where filter.
In the downer case, find Orders.ID=12345 first, and then do join.
For an inner join, WHERE and ON can be used interchangeably. In fact, it's possible to use ON in a correlated subquery. For example:
update mytable
set myscore=100
where exists (
select 1 from table1
inner join table2
on (table2.key = mytable.key)
inner join table3
on (table3.key = table2.key and table3.key = table1.key)
...
)
This is (IMHO) utterly confusing to a human, and it's very easy to forget to link table1 to anything (because the "driver" table doesn't have an "on" clause), but it's legal.
for better performance tables should have a special indexed column to use for JOINS .
so if the column you condition on is not one of those indexed columns then i suspect it is better to keep it in WHERE .
so you JOIN using the indexed columns, then after JOIN you run the condition on the none indexed column .
Normally, filtering is processed in the WHERE clause once the two tables have already been joined. It’s possible, though that you might want to filter one or both of the tables before joining them.
i.e, the where clause applies to the whole result set whereas the on clause only applies to the join in question.
They are equivalent, literally.
In most open-source databases (most notable examples, in MySql and postgresql) the query planning is a variant of the classic algorithm appearing in Access Path Selection in a Relational Database Management System (Selinger et al, 1979). In this approach, the conditions are of two types
conditions referring to a single table (used for filtering)
conditions referring to two tables (treated as join conditions, regardless of where they appear)
Especially in MySql, you can see yourself, by tracing the optimizer, that the join .. on conditions are replaced during parsing by the equivalent where conditions. A similar thing happens in postgresql (though there's no way to see it through a log, you have to read the source description).
Anyway, the main point is, the difference between the two syntax variants is lost during the parsing/query-rewriting phase, it does not even reach the query planning and execution phase. So, there's no question about whether they are equivalent in terms of performance, they become identical long before they reach the execution phase.
You can use explain, to verify that they produce identical plans. Eg, in postgres, the plan will contain a join clause, even if you didn't use the join..on syntax anywhere.
Oracle and SQL server are not open source, but, as far as I know, they are based equivalence rules (similar to those in relational algebra), and they also produce identical execution plans in both cases.
Obviously, the two syntax styles are not equivalent for outer joins, for those you have to use the join ... on syntax
Regarding your question,
It is the same both 'on' or 'where' on an inner join as long as your server can get it:
select * from a inner join b on a.c = b.c
and
select * from a inner join b where a.c = b.c
The 'where' option not all interpreters know so maybe should be avoided. And of course the 'on' clause is clearer.
a. WHERE clause: After joining, Records will be filtered.
b. ON clause - Before joining, Records (from right table) will be filtered.
To add onto Joel Coehoorn's response, I'll add some sqlite-specific optimization info (other SQL flavors may behave differently). In the original example, the LEFT JOINs have a different outcome depending on whether you use JOIN ON ... WHERE or JOIN ON ... AND. Here is a slightly modified example to illustrate:
SELECT *
FROM Orders
LEFT JOIN OrderLines ON Orders.ID = OrderLines.OrderID
WHERE Orders.Username = OrderLines.Username
versus
SELECT *
FROM Orders
LEFT JOIN OrderLines ON Orders.ID = OrderLines.OrderID
AND Orders.Username = OrderLines.Username
Now, the original answer states that if you use a plain inner join instead of a left join, the outcome of both queries will be the same, but the execution plan will differ. I recently realized that the semantic difference between the two is that the former forces the query optimizer to use the index associated with the ON clause, while the latter allows the optimizer to choose any index within the ON ... AND clauses, depending on what it thinks will work best.
Occasionally, the optimizer will guess wrong and you'll want to force a certain execution plan. In this case, let's say that the SQLite optimizer wrongly concludes that the fastest way to perform this join would be to use the index on Orders.Username, when you know from empirical testing that the index on Orders.ID would deliver your query faster.
In this case, the former JOIN ON ... WHERE syntax essentially allows you to force the primary join operation to occur on the ID parameter, with secondary filtering on Username performed only after the main join is complete. In contrast, the JOIN ON ... AND syntax allows the optimizer to pick whether to use the index on Orders.ID or Orders.Username, and there is the theoretical possibility that it picks the one that ends up slower.
It matters:
Look for instance,
This is when you are using WHERE clause at the end
where cat.category is null or cat.category <> 'OTHER'
and here you are using AND clause on join
category 'OTHER' or category is null (I don't know why it doesn't show not equal sign)
Since when you are joining it you are taking the filtred value as a NULL
this is my solution.
SELECT song_ID,songs.fullname, singers.fullname
FROM music JOIN songs ON songs.ID = music.song_ID
JOIN singers ON singers.ID = music.singer_ID
GROUP BY songs.fullname
You must have the GROUP BY to get it to work.
Hope this help.

How to count values from rows and display the result in columns

please help me
Oracle | Status| other columnns |
41 | A |
52 | W |
41 | A |
52 | W |
41 | W |
__________________
I need a resulting query that shows the count of Status in every Oracle like this:
Oracle | Total(A) | Total(W) |
41 | 2 | 1 |
52 | 0 | 2 |
Try this
with CTE AS
( select oracle,status from TableName)
select * from CTE
Pivot
(count(status) for status in ([A],[W]) ) as pvt
Try this:
select oracle, count(distinct status)
from your_table
group by oracle
You won't have the exact same result but you will have all the data you need to build that table.
You could also try some windows functions.
There are at least 2 ways to get that data:
1.
SELECT t1.oracle, ISNULL(Total_A, 0) As [Total (A)], ISNULL(Total_W,0) As [Total (W)]
FROM
(
SELECT oracle, count(status) As Total_A
FROM TableName
WHERE status = 'A'
GROUP BY oracle
) t1 INNER JOIN
(
SELECT oracle, count(status) As Total_W
FROM TableName
WHERE status = 'W'
GROUP BY oracle
) t2 ON(t1.oracle = t2.oracle)
This will give you the table you asked for, however, I will not recommend it as it is a terrible mess.
2.
SELECT oracle, status, COUNT(status)
FROM TableName
GROUP BY oracle, status
This will give you a table that you can then arrange in code to look like the table you requested in very little effort. Also, it is much cleaner and will be easy to handle a new status if introduced to the system.

Postgres: Query that can filter during table join

I have a postgres database with duplicated entries on one of the table. I would like to show the created_by columns
Table1
id | number
1 | 123
2 | 124
3 | 125
4 | 126
Table2
id | number | created_on
1 | 123 | 3/29
2 | 123 | 4/3
3 | 124 | 3/31
4 | 124 | 4/1
On table 2 number are duplicated. I would like to form a single query to list the following:
id | number | created_on
1 | 123 | 4/3
2 | 124 | 4/1
For duplicated entries only the latest entry will be included. How could I form that SQL query?
SELECT DISTINCT ON (Table1.number) Table1.id, Table2.number, Table2.create_on FROM Table1
JOIN Table2 ON Table1.number=Table2.number
ORDER BY Table2.create_on;
Actually I tried putting 'DISTINCT ON' and 'ORDER BY' in a single query (with JOIN) it gives me the following error:
SELECT DISTINCT ON expressions must match initial ORDER BY expressions
The columns in DISTINCT ON() have to be the first ones in the ORDER BY query, also if you want the latest created_on date you should order by created_on DESC
SELECT DISTINCT ON (Table1.number) Table1.id, Table2.number, Table2.created_on
FROM Table1
JOIN Table2
ON Table1.number=Table2.number
ORDER BY Table1.number,Table2.created_on DESC;
http://sqlfiddle.com/#!12/5538a/2
As you said in the comment: created_on=date_trunc('day', now()), so the data type of the field created_on is timestamp. Here is what you can do:
SELECT table_1.id, table_1.number, max(created_on) as created_on
FROM table_1
inner join table_2 using(number)
group by table_1.id, table_1.number

Efficient Date Comparisons in SQL

I hope this question provides all of the necessary information, but please do request more if anything is unclear. This is my first question on stack overflow so please bear with me.
I am running this query on SQL Server 2005.
I have a large derived dataset (i'll provide a small subset later) which has 4 fields;
ID,
Year,
StartDate,
EndDate
Within this data set the ID may (correctly) appear multiple times with different date combinations.
The question I have is what ways are there to identify if a record is 'new' I.E it's start date does not fall between the start and end date of any other records for the same id.
For an example take the data set below (I hope this table comes out correctly!);
+----+------+------------+------------+
| ID | Year | Start Date | End Date |
+----+------+------------+------------+
| 1 | 2007 | 01/01/2007 | 10/10/2007 |
| 1 | 2007 | 01/01/2007 | 05/04/2007 |
| 1 | 2007 | 05/04/2007 | 08/10/2007 |
| 1 | 2007 | 15/10/2007 | 20/10/2007 |
| 1 | 2007 | 25/10/2007 | 01/01/2008 |
| 2 | 2007 | 01/01/2007 | 01/01/2008 |
| 2 | 2008 | 01/01/2008 | 15/07/2008 |
| 2 | 2008 | 10/06/2008 | 01/01/2009 |
+----+------+------------+------------+
If we say nothing existed before 2007 then Row 1 and Row 6 are 'new' at that time.
Rows 2,3,7 and 8 are not 'new' as they either join the end of a previous record or overlap it to form a continuous date period (take rows 6 and 7 there are no 'breaks' between 01/01/2008 and 01/01/2009)
Row 4 and 5 would be considered a new record as it does not attach directly to the end of the previous period for ID 1 or overlap any of the other periods.
Currently to get this data set I have to put all of my data into temporary tables and then join them together on various fields to remove the records I don't want.
Firstly I remove rows where the startdate equals the enddate of another row for that ID (This would get rid of rows 3 and 7)
Then I remove rows where the the start date is between the startdate and enddate of other records for that ID (this would remove rows 2 and 8)
That would leave me withRows 1,4,5 and 6 as the 'new' records which is correct.
Is there a more efficient way to do this such as in some sort of loop, CTE or cough Cursor?
As per the above, if there is anything unclear don't hesitate to ask and I will try and provide you with the information you request.
Try
;with cte as
(
Select *, row_number() over (partition by id order by startdate) rn from yourtable
)
select distinct t1.*
from cte t1
left join cte t2
on t1.ID = t2.ID
and t1.EndDate>=t2.StartDate and t1.StartDate<=t2.EndDate
and t1.rn<>t2.rn
where t2.ID is null
or t1.rn=1
this should work, if you have a unique identifier for each row:
select * from
tbl t3
left outer join
(
select distinct t1.id as id_inside, t1.recno as recno_inside
from
tbl t1 inner join
tbl t2 on
t1.id = t2.id and
(t1.startdate <> t2.startdate or t1.enddate <> t2.enddate) and
(t1.startdate >= t2.startdate and t1.enddate <= t2.enddate)
) t4 on
t3.id = t4.id_inside and
t3.recno = t4.recno_inside
where
id_inside is null and
recno_inside is null
sqlfiddle

Resources