Subquery with join statement - sql

I don't understand why it doesn't allow me join inside a subquery.
Please consider the following section of code:
SELECT c.num_id
FROM (
SELECT *
FROM staff_salary as a
FULL JOIN staff_profile as b
ON a.num_id = b.num_id
) as c
I'm receiving the error:
The column 'num_id' was specified multiple times for 'c'.
Why is this happening? When I run it without the join statement the subquery works just perfectly.

The field num_id is present in both staff_salary and staff_profile.
As you are selecting with *, sql has no way to know if you refer to staff_salary.num_id o staff_profile.num_id
You will have to replace * for the list of needed fields, for instance:
SELECT c.num_id FROM (
SELECT a.num_id
FROM staff_salary as a
FULL JOIN staff_profile as b
ON a.num_id = b.num_id
) as c

What are you trying to do? If you want all num_id in either table, then use union:
select num_id
from staff_salary
union -- on purpose to remove duplicates
select num_id
from staff_profile;

Use specific column in the inner query. Wild (*) is throwing an exception.
SELECT c.num_id
FROM (
SELECT b.num_id
FROM staff_salary as a
FULL JOIN staff_profile as b
ON a.num_id = b.num_id
) as c

Related

Crosstab query with CTE returns error: relation "cte" does not exist

I have two schemas on my PostgreSQL server, and I'm trying to create a pivoted table:
WITH cte AS (
SELECT l.fcid, t.fixture_code, COUNT(f.fixture_type_id) AS count
FROM aim.locations as l
JOIN aim.fixture_instances as f
ON l.id = f.location_id
JOIN aim.fixture_types as t
ON f.fixture_type_id = t.id
GROUP BY l.fcid, t.fixture_code
)
SELECT *
FROM lab.CROSSTAB('SELECT fcid, fixture_code, SUM(count) FROM cte group by 1,2 order by 1,2',
'Select DISTINCT fixture_code from cte order by 1')
AS CT (FCID integer, "fx1" bigint, "fx2" bigint)
ORDER BY fcid;
However, I receive an error:
ERROR: relation "cte" does not exist
LINE 1: Select DISTINCT fixture_code from cte order by 1
The query worked when I had only one schema.
I use a CTE so I could create a view with the query.
What's wrong here?
In fact, you don't need the outer SELECT of the query string argument at all. The added sum(count) changes nothing in this constellation. The query in the CTE already delivers the end result to be fed to crosstab(). Get rid of the CTE altogether - thereby also fixing the immediate cause of the error:
SELECT *
FROM lab.crosstab(
$$
SELECT l.fcid, t.fixture_code, count(*) AS cnt
FROM aim.locations l
JOIN aim.fixture_instances f ON l.id = f.location_id
JOIN aim.fixture_types t ON f.fixture_type_id = t.id
GROUP BY 1,2
ORDER BY 1,2
$$
, $$VALUES ('fx1'), ('fx2')$$
) AS ct(fcid int, fx1 bigint, fx2 bigint);
Some other things:
There is no point in running SELECT DISTINCT when you have to spell out corresponding columns names in the column definition list anyway. Replaced it with a plain VALUES expression.
f.fixture_type_id is NOT NULL by definition of the query, so use the faster equivalent count(*).
Basics here:
PostgreSQL Crosstab Query

Remove duplicates from result in sql

i have following sql in java project:
select distinct * from drivers inner join licenses on drivers.user_id=licenses.issuer_id
inner join users on drivers.user_id=users.id
where (licenses.state='ISSUED' or drivers.status='WAITING')
and users.is_deleted=false
And result i database looks like this:
And i would like to get only one result instead of two duplicated results.
How can i do that?
Solution 1 - That's Because one of data has duplicate value write distinct keyword with only column you want like this
Select distinct id, distinct creation_date, distinct modification_date from
YourTable
Solution 2 - apply distinct only on ID and once you get id you can get all data using in query
select * from yourtable where id in (select distinct id from drivers inner join
licenses
on drivers.user_id=licenses.issuer_id
inner join users on drivers.user_id=users.id
where (licenses.state='ISSUED' or drivers.status='WAITING')
and users.is_deleted=false )
Enum fields name on select, using COALESCE for fields which value is null.
usually you dont query distinct with * (all columns), because it means if one column has the same value but the rest isn't, it will be treated as a different rows. so you have to distinct only the column you want to, then get the data
I suspect that you want left joins like this:
select *
from users u left join
drivers d
on d.user_id = u.id and d.status = 'WAITING' left join
licenses l
on d.user_id = l.issuer_id and l.state = 'ISSUED'
where u.is_deleted = false and
(d.user_id is not null or l.issuer_id is not null);

Can we select first row of data from column in sql?

I have a table with multiple data for same ID. I want to get the first row data for the ID.
I have added the below SQL that I have tried.
SELECT
"client"."id",
"client"."company_name",
"client_details"."address"
from Client
LEFT OUTER JOIN "client_details" ON ("client"."id" = "client_details"."client_id")
Since I have multiple address for the same ID, can we get only the first id?
Currently the output I get is 2 rows with different addresses.
You can add to your SQL LIMIT 1 and in case you want to be sure the order you can also add to your SQL ORDER BY...
You can use distinct on:
select distinct on (c.id) c.id, c.company_name, cd.address
from Client c left join
client_details cd
on c.id = cd.client_id
order by c.id, ?;
The ? is for the column that specifies the ordering (the definition of "first"). I am guessing that cd.id is what you want.
Note that this query removes the double quotes and introduces table aliases. This is easier on both the eyes (to read) and the fingers (to type).
use row_number()
select * from
(
SELECT
"client"."id",
"client"."company_name",
"client_details"."address",row_number() over(partition by "client"."id" order by "client_details"."address") as rn
from Client
LEFT OUTER JOIN "client_details" ON "client"."id" = "client_details"."client_id"
)A where rn=1
If there is a field you can order the results by you could use a lateral join e.g.
SELECT
"client"."id",
"client"."company_name",
"client_details"."address"
from Client
left join lateral (
select *
from client_details cd
where cd.client_id = client.id
order by [some_ordering_field]
limit 1
) "client_details" on true

How to left join column in other way

I want to map right column to left but i am getting error at select statement as Incorrect syntax near 'select'.Expecting ID
create table [AdventureWorks2014].[abc] as
select a.*,
b.*
from [Production].[Product] a
left join(
select distinct ProductID,Shelf
from [Production].[ProductInventory]
)b
on a.ProductID = b. ProductID;
Try using SELECT INTO:
select p.*, pi.shelf
into [AdventureWorks2014].[abc]
from [Production].[Product] p left join
(select distinct ProductID, Shelf
from [Production].[ProductInventory] pi
) pi
on p.ProductID = pi.ProductID;
Notes:
I am not aware that SQL Server supports CREATE TABLE AS.
The columns in a table need to have unique names. If you use *, you will get ProductId twice.
Abbreviations of the table names is the best naming conventions; meaningless letters such as a and b should be avoided.

Query for missing items in a table

I have a table of airport code pairs:
|iata|icao|
-----------
|ORD |KORD|
|JFK |KJFK|
|LAX |KLAX|
|SFO |KSFO|
I want to run a query that will return the codes that do not exist in this table, so if I run a query (against the iata column) containing ATL,ORD,MIA,SFO it would return ATL and MIA since neither of those exist in my table. Is this possible?
If you have a query that runs code, here is one way:
select mc.*
from (<your query goes here>) mc
where mc.iata not in (select iata from AirportCodePairs acp)
You can also do this with a left outer join and comparison to NULL. I would recommend an index on iata in the pairs table.
Or, if you don't have a query, you can do:
select mc.*
from (select 'ATL' as code union all
select 'ORD' union all
select 'MIA' union all
select 'SFO'
) mc
where mc.iata not in (select iata from AirportCodePairs acp)
You can create a table with the values you are searching for and then do a JOIN:
CREATE TABLE tmp ( code char(3) NOT NULL);
INSERT INTO tmp (code) VALUES ('ATL'), ('ORD'), ('MIA'), ('SFO');
SELECT code FROM tmp
LEFT OUTER JOIN airportcode as ac ON tmp.code = ac.iata
WHERE ac.iata IS NULL
in oracle you could use minus command example
select your_columns from tableA minus select your_columns from tableB
note that both must have same columns and types and lengths or it will not work.
if type is different do cast, to_char, to_date or whatever function is necessary to get types the same. Note if you do have to do one of these or any oracle function call in where clause then use function based indexes. For example, if to_upper is called in where clause like this
select * from tableName a where to_upper(last_name)='SIMPSON'
an index on this would be created as follows
create index ixt on tableName(to_uppper(last_name));