Full outer join not showing unmatched rows - SQL - tsql

I am trying to do a full outer join of two tables, matching them with the "PO Product Code" of table 1 and "Product Code" of table 2. Each time I attempt to do this, there are a few product codes that are left out:
CABSCABS0000, DOORINTD0015, FLORCARP0001, EXCL0001, and FLORTILE0000
Each of these product codes are in table 2, but not in table 1.
Here are the screenshots of the tables I am working with.
https://i.imgur.com/pFAfrAb.png
https://i.imgur.com/k0a3o57.png
And here is the code that I have tried:
SELECT cost.[Actual Close]
,cost.[Project Name]
,cost.[Lot]
,cost.[Model]
,cost.[Elev]
,cost.[PO Product Code]
,cost.[Invoiced + Open] AS 'Invoiced + Open'
,rev.[Gross Sale] AS 'Gross Sale'
FROM Table1 cost FULL OUTER JOIN
Table2 rev
ON rev.[Product Code] = cost.[PO Product Code]
WHERE rev.[Project Name] = cost.[Project Name] AND
rev.[Lot] = cost.[Lot];
I must also mention that the Product Code is specific to each Project Name and Lot, which is why that is added to the 'WHERE' clause.
Here is the output I got, which is missing the 5 craft codes listed above.
https://i.imgur.com/EoMFc9v.png

The FULL JOIN returns NULL values in columns for rows that do not match in either of the tables. Your WHERE clause filters these out -- because NULL comparisons almost never evaluate to "true" (the exception is IS NULL and NULL-safe comparisons).
What you want to do is move these conditions to the ON clause. That is where they belong anyway, because they are really JOIN conditions:
FROM Table1 cost FULL OUTER JOIN
Table2 rev
ON rev.[Product Code] = cost.[PO Product Code] AND
rev.[Project Name] = cost.[Project Name] AND
rev.[Lot] = cost.[Lot];

Its because of your where clause
rev.[Project Name] = cost.[Project Name]
AND rev.[Lot] = cost.[Lot];
Since those items that you mentioned are not in table A but are in table B, you are basically removing them via WHERE clause.
If you want those 5 Items to show, try removing the where clause, then run the query again.

Related

Joining one table twice in postgresql

I have two columns in the same table that I want to join in Postgresql but for some reason I’m getting this error. Don’t know how to figure it out. Please help.
[42P01] ERROR: relation "a" does not exist
Position: 10
X table contains two pools(ABC,XYZ), ids, numbers and description. If an ID exists in one pool but not in the other, it should update description column to “ADD”. Pools need to be joined on number.
UPDATE A
SET A.Description = 'ADD'
FROM X AS A
LEFT JOIN X AS B ON B.number = A.number
AND B.id = 'ABC'
WHERE A.id = 'XYZ'
AND B.number IS NULL
AND A.Description IS NULL;
With standard SQL you can't do a join as part of an update, but what you can do is include a subquery to select the id's to update. The subquery can contain a join. I'm not entirely clear on what you're actually trying to accomplish, but you could do something like this:
UPDATE x SET description='ADD' WHERE number IN (
SELECT a.number FROM x AS a
LEFT OUTER JOIN x AS b ON a.number=b.number AND a.id='XYZ' AND b.id='ABC'
WHERE b.number IS NULL
);
This will join the table x with itself and will select (and update) any numbers's that don't have a matching number in the 'ABC' and 'XYZ' zone.
PostgreSQL does have a UPDATE FROM syntax that does let you update with complex subqueries. It's more flexible but it's non-standard. You can find an example of this type of query here.

oracle: grouping on merged columns

I have a 2 tables FIRST
id,rl_no,adm_date,fees
1,123456,14-11-10,100
2,987654,10-11-12,30
3,4343,14-11-17,20
and SECOND
id,rollno,fare,type
1,123456,20,bs
5,634452,1000,bs
3,123456,900,bs
4,123456,700,bs
My requirement is twofold,
1, i first need to get all columns from both tables with common rl_no. So i used:
SELECT a.ID,a.rl_no,a.adm_date,a.fees,b.rollno,b.fare,b.type FROM FIRST a
INNER JOIN
SECOND b ON a.rl_no = b.rollno
The output is like this:
id,rl_no,adm_date,fees,rollno,fare,type
1,123456,14-11-10,100,123456,20,bs
1,123456,10-11-12,100,123456,900,bs
1,123456,14-11-17,100,123456,700,bs
2,Next i wanted to get the sum(fare) of those rollno that were common between the 2 tables and also whose fare >= fees from FIRST table group by rollno and id.
My query is:
SELECT x.ID,x.rl_no,,x.adm_date,x.fees,x.rollno,x.type,sum(x.fare) as "fare" from (SELECT a.ID,a.rl_no,a.adm_date,a.fees,b.rollno,b.fare,b.type FROM FIRST a
INNER JOIN
SECOND b ON a.rl_no = b.rollno) x, FIRST y
WHERE x.rollno = y.rl_no AND x.fare >= y.fees AND x.type IS NOT NULL GROUP BY x.rollno,x.ID ;
But this is throwing in exceptions.
ORA-00979: not a GROUP BY expression
00979. 00000 - "not a GROUP BY expression"
The expected output will be like this:
id,rollno,adm_date,fare,type
1,123456,14-11-10,1620,bs
So could someone care to show an oracle newbie what i'm doing wrong here?
It looks like there's a couple different problems here;
Firstly, you're trying to group by an x.ID column which doesn't exist; it looks like you'll want to add ID to the selected columns in your sub-query.
Secondly, when aggregating with GROUP BY, all selected columns need to be either listed in the GROUP BY statement or aggregated. If you're grouping by rollno and ID, what do you want to have happen to all the extra values for adm_date, fees, and type? Are those always going to be the same for each distinct rollno and ID pair?
If so, simply add them to the GROUP BY statement, ie,
GROUP BY adm_date, fees, type, rollno, ID
If not, you'll need to work out exactly how you want to select which one to be output; If you've got output like your example (adding in an ID column here)
ID,adm_date,fees,rollno,fare,type
1,14-11-10,100,123456,20,bs
1,10-11-12,100,123456,900,bs
1,14-11-17,100,123456,700,bs
Call that result set 'a'. If I run;
SELECT a.ID, a.rollno, SUM(a.fare) as total_fare
FROM a
GROUP BY a.ID, a.rollno
Then the result will be a single row;
ID,rollno,total_fare
1,123456,1620
So, if you also select the adm_date, fees, and type columns, oracle has no idea what you mean to do with them. You're not using them for grouping, and you're not telling oracle how you want to pick which one to use.
You could do something like
SELECT a.ID,
FIRST(a.adm_date) as first_adm_date,
FIRST(a.fees) as first_fees,
a.rollno,
SUM(a.fare) as total_fare,
FIRST(a.type) as first_type
FROM a
GROUP BY a.ID, a.rollno
Which would give the result;
ID,first_adm_date,first_fees,rollno,total_fare,first_type
1,14-11-10,100,123456,1620,bs
I'm not sure if that's what you mean to do though.

How to use GROUP BY with Firebird?

I'm trying create a SELECT with GROUP BY in Firebird but I can't have any success. How could I do this ?
Exception
Can't format message 13:896 -- message file C:\firebird.msg not found.
Dynamic SQL Error.
SQL error code = -104.
Invalid expression in the select list (not contained in either an aggregate function or the GROUP BY clause).
(49,765 sec)
trying
SELECT FA_DATA, FA_CODALUNO, FA_MATERIA, FA_TURMA, FA_QTDFALTA,
ALU_CODIGO, ALU_NOME,
M_CODIGO, M_DESCRICAO,
FT_CODIGO, FT_ANOLETIVO, FT_TURMA
FROM FALTAS Falta
INNER JOIN ALUNOS Aluno ON (Falta.FA_CODALUNO = Aluno.ALU_CODIGO)
INNER JOIN MATERIAS Materia ON (Falta.FA_MATERIA = Materia.M_CODIGO)
INNER JOIN FORMACAOTURMAS Turma ON (Falta.FA_TURMA = Turma.FT_CODIGO)
WHERE (Falta.FA_CODALUNO = 238) AND (Turma.FT_ANOLETIVO = 2015)
GROUP BY Materia.M_CODIGO
Simple use of group by in firebird,group by all columns
select * from T1 t
where t.id in
(SELECT t.id FROM T1 t
INNER JOIN T2 j ON j.id = t.jid
WHERE t.id = 1
GROUP BY t.id)
Using GROUP BY doesn't make sense in your example code. It is only useful when using aggregate functions (+ some other minor uses). In any case, Firebird requires you to specify all columns from the SELECT column list except those with aggregate functions in the GROUP BY clause.
Note that this is more restrictive than the SQL standard, which allows you to leave out functionally dependent columns (ie if you specify a primary key or unique key, you don't need to specify the other columns of that table).
You don't specify why you want to group (because it doesn't make much sense to do it with this query). Maybe instead you want to ORDER BY, or you want the first row for each M_CODIGO.

comprare aggregate sum function to number in postgres

I have the next query which does not work:
UPDATE item
SET popularity= (CASE
WHEN (select SUM(io.quantity) from item i NATURAL JOIN itemorder io GROUP BY io.item_id) > 3 THEN TRUE
ELSE FALSE
END);
Here I want to compare each line of inner SELECT SUM value with 3 and update popularity. But SQL gives error:
ERROR: more than one row returned by a subquery used as an expression
I understand that inner SELECT returns many values, but can smb help me in how to compare each line. In other words make loop.
When using a subquery you need to get a single row back, so you're effectively doing a query for each record in the item table.
UPDATE item i
SET popularity = (SELECT SUM(io.quantity) FROM itemorder io
WHERE io.item_id = i.item_id) > 3;
An alternative (which is a postgresql extension) is to use a derived table in a FROM clause.
UPDATE item i2
SET popularity = x.orders > 3
FROM (select i.item_id, SUM(io.quantity) as orders
from item i NATURAL JOIN itemorder io GROUP BY io.item_id)
as x(item_id,orders)
WHERE i2.item_id = x.item_id
Here you're doing a single group clause as you had, and we're joining the table to be updated with the results of the group.

t sql query returns duplicate values

I know this is an often asked question, but I've tried to resolve this myself and could not.
I've got 2 tables to join and now it's returning a duplicate value from the right table.
select am.Journal
,am.EntryNumber
,am.PayInvoice
,am.PayDiscAllowed
,am.PayTaxAmtDisc
,am.PayGrossPayment
,tm.*
from CshJnlPay am right join
(select
Invoice
,SUM(NetSalesValue) as NetSalesValue
,SUM(DiscValue) as DiscValue
,SUM(TaxValue) as TaxValue
,SUM(QtyInvoiced) as QtyInvoiced
from Salesdetail
group by Invoice) tm
on am.PayInvoice = tm.Invoice
where Invoice = 'C90831'
If the query returns 2 rows with the same data from the right table then you have 2 rows in the left table with the same invoice number...
You should check the left table with this query
Select * from CshJnlPay where PayInvoice = 'C90831'
You should get two rows.