Referencing an aliased subquery in Oracle - sql

I have the following query :
select
A.A_ID,
B.Lib,
A.Lib,
C.Lib,
(SELECT count(*) FROM X WHERE A.A_ID = X.A_ID) AS countX,
(SELECT count(*) FROM Y WHERE A.A_ID = Y.A_ID) AS countY,
(SELECT count(*) FROM Z WHERE A.A_ID = Z.A_ID) AS countZ
from
A
left outer join
C
on A.C_ID=C.C_ID
left outer join
B
on A.B_ID=B.B_ID
WHERE
countX = 2 AND countY = 3
ORDER BY
countZ DESC;
But this gives me the following error:
SQL Error [904] [42000]: ORA-00904: "COL_5_0_" : identificateur non
valide
How can I solve this ?

try like below, i think you missed type group by it would be order by
with cte as
(
select
A.A_ID,
B.Lib,
A.Lib,
C.Lib,
(SELECT count(*) FROM X WHERE A.A_ID = X.A_ID) AS countX,
(SELECT count(*) FROM Y WHERE A.A_ID = Y.A_ID) AS countY,
(SELECT count(*) FROM Z WHERE A.A_ID = Z.A_ID) AS countZ
from
A
left outer join
C
on A.C_ID=C.C_ID
left outer join
B
on A.B_ID=B.B_ID
) select * from cte where countX = 2 AND countY = 3
Order BY
countZ DESC

Related

SQL Select count of items from a child table with a where clause

SQL Query :
select c.cid, la.lid, b.bid, b.type
from c c
left join la la on c.cid = la.cid
left join b b on la.lid = b.lid
where b.type = 'Primary';
There are three tables c -> la -> b
I need the total count of 'b' for any given 'la' but I need to have " b.type = 'Primary' " in the where clause for other purposes.
b.type has two types - Primary and Secondary but I want a count of total number of 'b' (Primary and Secondary) Can somebody give any hints ? It would be a good learning for me. Thanks.
sample data and desired o/p
Try this:
SELECT
c.cid,
la.lid,
b.bid,
b.type,
d.cbdi
FROM c c
LEFT JOIN la la ON c.cid = la.lid
LEFT JOIN b b ON la.lid2 = b.lid2
LEFT JOIN (
SELECT
la.lid,
COUNT(b.bid) AS cbid
FROM la la
LEFT JOIN b b ON la.lid2 = b.lid2
GROUP BY la.lid
) d ON la.lid = d.lid
WHERE
b.type = 'Primary';
You can not have row having secondary in desired output as per your attached screenshot because of clause where b.type = 'Primary'. Please check again, looks like your requirement is not clear.
You seem to want to show all rows unaggregated but show an aggregation (the b count) along. This is done with a window function, COUNT OVER in your case.
select c.cid, la.lid, b.bid, b.type, count(*) over (partition by la.lid) as number_of_b
from la
join c on c.cid = la.cid
join b on b.lid = la.lid
order by c.cid, la.lid, b.bid;
If you want to restrict this to la that have at least one primary b, extend this query accordingly:
select cid, lid, bid, type, number_of_b
from
(
select
c.cid, la.lid, b.bid, b.type,
count(*) over (partition by la.lid) as number_of_b,
max(case when b.type = 'Primary' then 1 else 0 end) over (partition by la.lid)
as has_primary_b
from la
join c on c.cid = la.cid
join b on b.lid = la.lid
order by c.cid, la.lid, b.bid
)
where has_primary_b = 1;
One solution would be to join table b twice on for selecting only the Primary records and one to count all. Something like:
select c.cid, la.lid, count(bt.id)
from c c
join la la on c.cid = la.cid
join b b on la.lid = b.lid
join b bt on la.lid = bt.lid
where b.type = 'Primary'
group by c.cid, la.lid;

Postgres 8.4 and Rails4.2.3 ActiveRecord::StatementInvalid Error

PG::Error: ERROR: column "a.id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT A.id, A.name, COUNT(DISTINCT tendercats.tender_Id) as...
^
SELECT A.id, A.name,
COUNT(DISTINCT tendercats.tender_Id) as total
FROM tender_categories A
LEFT JOIN tender_categories B ON A.id = B.tender_category_id
LEFT JOIN tendercats ON (tendercats.tender_category_id = B.id) OR (tendercats.tender_category_id = A.id)
JOIN tenders ts ON tendercats.tender_category_id = ts.id
WHERE A.tender_category_id is NULL
AND (ts.cdate > '2015-08-31')
AND ts.language_id = 1
ORDER BY A.id, A.name

First query data is used in second query

I have a query get_product:
select A.product_id,
A.name, A.description, A.type_id,
B.series_name
product_data A
inner join
series B
on A.series_raw_id = B.series_raw_id
where A.product_id = 503061
and A.registration_type_id = 4
order by B.series_name
and second query
select B.series_name,
A.TEMPACC_STATUS
FROM
ACCESS_FACT A
inner join
**get_product** B
on A.TEMPACC_PRODUCT_ID = B.product_id
where A.TEMPACC_DATE_ID between 6717 and 6808
and A.reason_id_total = 0
group by Series_name,
STATUS
In the second query we use data from first query (get_product is the first query). How do I get that table here?
You could use the WITH clause.
For example,
WITH get_product AS
(SELECT A.product_id,
A.name,
A.description,
A.type_id,
B.series_name product_data A
INNER JOIN series B
ON A.series_raw_id = B.series_raw_id
WHERE A.product_id = 503061
AND A.registration_type_id = 4
ORDER BY B.series_name
)
SELECT B.series_name,
A.TEMPACC_STATUS
FROM ACCESS_FACT A
INNER JOIN get_product B
ON A.TEMPACC_PRODUCT_ID = B.product_id
WHERE A.TEMPACC_DATE_ID BETWEEN 6717 AND 6808
AND A.reason_id_total = 0
GROUP BY Series_name,
STATUS;
Or, you could use an INLINE VIEW
SELECT B.series_name,
A.TEMPACC_STATUS
FROM ACCESS_FACT A
INNER JOIN
(SELECT A.product_id,
A.name,
A.description,
A.type_id,
B.series_name product_data A
INNER JOIN series B
ON A.series_raw_id = B.series_raw_id
WHERE A.product_id = 503061
AND A.registration_type_id = 4
ORDER BY B.series_name
) B ON A.TEMPACC_PRODUCT_ID = B.product_id
WHERE A.TEMPACC_DATE_ID BETWEEN 6717 AND 6808
AND A.reason_id_total = 0
GROUP BY Series_name,
STATUS;

Select only the rows where column values appear more than once

I have a select statement similar to the following:
select *
from A
inner join B on A.id_x = B.id_x
inner join C on B.id_y = C.id_y
inner join D on C.id_z = D.id_z
where
A.date > '2014-01-01'
and A.id_y = 154
and D.id_t = 2
What I want is to do something like this and count(A.id_x) > 1, which returns only the parts of the original select which repeat on A.id_x.
Is this possible?
EDIT:
I just tried to solve it using temp tables, with the code I got from T-SQL Insert into table without having to specify every column
Select * Into
#tmpBigTable
From [YourBigTable]
But I got an error message because my tables have the same column names, A.id_x and B.id_x, for example.
"Column names in each table must be unique."
Is there some way to force the issue, or declare arbitrary naming extensions?
select *
from A
inner join B on A.id_x = B.id_x
inner join C on B.id_y = C.id_y
inner join D on C.id_z = D.id_z
where
A.date > '2014-01-01'
and A.id_y = 154
and D.id_t = 2
AND A.id_x IN
(
SELECT A.id_x FROM A
GROUP BY A.id_x
HAVING count(A.id_x)>1);
You can do this with window functions:
select *
from (select *, count(*) over (partition by A.id_x) as cnt
from A inner join
B
on A.id_x = B.id_x inner join
C
on B.id_y = C.id_y inner join
D
on C.id_z = D.id_z
where A.date > '2014-01-01' and A.id_y = 154 and D.id_t = 2
) abcd
where cnt > 1;

Select from Many-to-Many with GroupBy

I have three entities:
Cue(id, name)
Reaction(id, name)
Freqs(id, cue_id FK, reaction_id FK, some_other_data)
I want to count number of (cue, reaction) pairs like (cue.name, reaction.name, count)
I already wrote a query
SELECT
a.cue_id,
a.reaction_id,
Count(*) as freq
FROM
rdb_freqs a
JOIN rdb_reaction b ON a.cue_id=b.id
JOIN rdb_cue c ON a.reaction_id=c.id
GROUP BY a.cue_id, a.reaction_id
ORDER BY freq DESC;
But how should I replace 'id' with 'name'?
SELECT distinct
c.name cue_name,
b.name reaction_name,
(SELECT
Count(*)
FROM
rdb_freqs a1
where
a1.cue_id = a.cue_id and
a1.reaction_id = a.reaction_id
) as count
FROM
rdb_freqs a
inner JOIN rdb_reaction b ON a.reaction_id = b.id
inner JOIN rdb_cue c ON a.cue_id = c.id
order by count desc
SQLfiddle sample (written in oracle)
SELECT
c.name as cue_name,
b.name as reacion_name,
Count(*) as freq
FROM
rdb_freqs a
JOIN rdb_reaction b ON a.cue_id=b.id
JOIN rdb_cue c ON a.reaction_id=c.id
GROUP BY c.name, b.name
ORDER BY freq DESC;
SELECT
FROM rdb_freq f
INNER JOIN (
SELECT
a.cue_id,
a.reaction_id,
Count(*) as freq
FROM
rdb_freqs a
JOIN rdb_reaction b ON a.cue_id=b.id
JOIN rdb_cue c ON a.reaction_id=c.id
GROUP BY a.cue_id, a.reaction_id
) AS tot ON f.cue_id = tot.cue_id
INNER JOIN reaction