Subqueries with different universes - sql

I have an Oracle DB and I need to run a select with sub selects, however, none of them share the same table universe, therefore, I would need to do something like this:
SELECT (
SELECT COUNT(*)
FROM user_table
) AS tot_user,
(
SELECT COUNT(*)
FROM cat_table
) AS tot_cat,
(
SELECT COUNT(*)
FROM course_table
) AS tot_course
I know this is possible at other databases but I need something like this for Oracle.
Can someone help?

To make this work in oracle, add from dual to the end:
SELECT (SELECT COUNT(*)
FROM user_table
) AS tot_user,
(SELECT COUNT(*)
FROM cat_table
) AS tot_cat,
(SELECT COUNT(*)
FROM course_table
) AS tot_course
FROM dual;
A database independent way of writing the query is:
select tot_user, tot_cat, tot_course
from (SELECT COUNT(*) as tot_user
FROM user_table
) u cross join
(SELECT COUNT(*) as tot_cat
FROM cat_table
) c cross join
(SELECT COUNT(*) as tot_course
FROM course_table
) ct;

Related

Joining a subquery using an outer column that uses a group function

So this one should be pretty simple for most of you:
My table has an ID, an order_id and a status.
The same order_id may have several IDs.
What I need to do is get the last ID from each order_id, which is pretty simple:
SELECT order_id, max(ID) AS last_id
FROM mytable
GROUP BY order_id
Now, I also need to get the status that is linked to last ID, so what I was trying to do was:
SELECT order_id, max(ID) AS last_id, x.status
FROM mytable t
LEFT JOIN (SELECT ID, status
FROM mytable) x ON last_id = x.ID
I know I'm not allowed to use the last_id alias to join the subquery, as it says it does not exist. So how do I go about this?
You can't use the alias in the FROM or in the WHERE parts of the query, you should use max(t.ID):
SELECT order_id, max(t.ID) AS last_id, x.status
FROM mytable t
LEFT JOIN (SELECT ID, status
FROM mytable) x ON MAX(t.ID) = x.ID
You can also wrap the query as a subquery and then do the join using the alias:
SELECT t.order_id, t.last_id, x.status
FROM (
SELECT order_id, max(ID) AS last_id
FROM mytable
) t
LEFT JOIN mytable x
ON t.last_id = x.ID
An alternative is to DISTINCT ON the column order_id and then apply max() on id.
SELECT DISTINCT ON (order_id)
order_id, max(id) AS last_id,
status
FROM mytable
GROUP BY order_id,status;
Demo: db<>fiddle

Get Distinct From Multiple Similar Tables

I have this query to join a couple tables and get distinct values, it looks something like this:
SELECT DISTINCT [TrackingCode]
,[Opponent]
,CONCAT([TrackingCode], ' | ', [Opponent]) AS RowName
,[MultiYrEvent]
,[Identifier]
FROM [BUDGET_FY2014].[dbo].[TrackingCodes]
INNER JOIN
(
SELECT *
FROM [BUDGET_FY2014].[dbo].[Transactions]
WHERE Report='2377010003'
) AS T
ON T.EventCode LIKE CAST(TrackingCodes.TrackingCode AS nvarchar(20))+'%'
ORDER BY TrackingCode ASC
It works fine. However, I've got multiple Transactions tables with the same schema for the first and second previous years relative to the Transactions table, and I'd like to see distinct values from all three tables. So for example, if I copy/paste this query and change [Transactions] to [Transactions_Yr1] or [Transactions_Yr2], then I get the data I want from those tables. But, I want to combine the three. If I try to join them all, I get no results returned. I sort of understand why this doesn't work, but I don't know where to go from here:
SELECT DISTINCT [TrackingCode]
,[Opponent]
,CONCAT([TrackingCode], ' | ', [Opponent]) AS RowName
,[MultiYrEvent]
,[Identifier]
FROM [BUDGET_FY2014].[dbo].[TrackingCodes]
INNER JOIN
(
SELECT *
FROM [BUDGET_FY2014].[dbo].[Transactions]
WHERE Report='2377010003'
) AS T
ON T.EventCode LIKE CAST(TrackingCodes.TrackingCode AS nvarchar(20))+'%'
INNER JOIN
(
SELECT *
FROM [BUDGET_FY2014].[dbo].[Transactions_Yr1]
WHERE Report='2377010003'
) AS T1
ON T1.EventCode LIKE CAST(TrackingCodes.TrackingCode AS nvarchar(20))+'%'
INNER JOIN
(
SELECT *
FROM [BUDGET_FY2014].[dbo].[Transactions_Yr2]
WHERE Report='2377010003'
) AS T2
ON T2.EventCode LIKE CAST(TrackingCodes.TrackingCode AS nvarchar(20))+'%'
ORDER BY TrackingCode ASC
Any advice would be appreciated!
Try use UNION ALL clausele, e.g.:
SELECT DISTINCT [FILDS]
FROM (
SELECT *
FROM [BUDGET_FY2014].[dbo].[Transactions]
WHERE Report='2377010003'
UNION ALL
SELECT *
FROM [BUDGET_FY2014].[dbo].[Transactions_Yr1]
WHERE Report='2377010003'
UNION ALL
SELECT *
FROM [BUDGET_FY2014].[dbo].[Transactions_Yr2]
WHERE Report='2377010003'
)
ORDER BY TrackingCode ASC
have you tried unioning your transaction tables together?
Reference: https://msdn.microsoft.com/en-us/library/ms180026.aspx
SELECT DISTINCT [TrackingCode]
,[Opponent]
,CONCAT([TrackingCode], ' | ', [Opponent]) AS RowName
,[MultiYrEvent]
,[Identifier]
FROM [BUDGET_FY2014].[dbo].[TrackingCodes]
INNER JOIN
(
SELECT * FROM(
SELECT *
FROM [BUDGET_FY2014].[dbo].[Transactions]
WHERE Report='2377010003'
) AS T
ON T.EventCode LIKE CAST(TrackingCodes.TrackingCode AS nvarchar(20))+'%'
Union
(
SELECT *
FROM [BUDGET_FY2014].[dbo].[Transactions_Yr1]
WHERE Report='2377010003'
) AS T1
ON T1.EventCode LIKE CAST(TrackingCodes.TrackingCode AS nvarchar(20))+'%'
Union
(
SELECT *
FROM [BUDGET_FY2014].[dbo].[Transactions_Yr2]
WHERE Report='2377010003'
) AS T2
ON T2.EventCode LIKE CAST(TrackingCodes.TrackingCode AS nvarchar(20))+'%'
)
ORDER BY TrackingCode ASC

ODBC Firebird Sql Query - Syntax

Trying to get an slightly more complex sql statement structured but can't seem to get the syntax right. Trying to select counts, of various columns, in two different tables.
SELECT
SUM(ColumninTable1),
SUM(Column2inTable1),
COUNT(DISTINCT(Column3inTable1))
FROM TABLE1
This works, however I can't for the life of me figure out how to add in a COUNT(DISTINCT(Column1inTable2) FROM TABLE2 with what syntax.
There are several solutions you can take:
Disjunct FULL OUTER JOIN
SELECT
SUM(MYTABLE.ID) as theSum,
COUNT(DISTINCT MYTABLE.SOMEVALUE) as theCount,
COUNT(DISTINCT MYOTHERTABLE.SOMEOTHERVALUE) as theOtherCount
FROM MYTABLE
FULL OUTER JOIN MYOTHERTABLE ON 1=0
UNION two queries and leave the column for the other table null
SELECT
MAX(theSum) as theSum,
MAX(theCount) as theCount,
MAX(theOtherCount) AS theOtherCount
FROM (
SELECT
SUM(ID) as theSum,
COUNT(DISTINCT SOMEVALUE) as theCount,
NULL as theOtherCount
FROM MYTABLE
UNION ALL
SELECT
NULL,
NULL,
COUNT(DISTINCT SOMEOTHERVALUE)
FROM MYOTHERTABLE
)
Query 'with a query per column' against a single record table (eg RDB$DATABASE)
SELECT
(SELECT SUM(ID) FROM MYTABLE) as theSum,
(SELECT COUNT(DISTINCT SOMEVALUE) FROM MYTABLE) as theCount,
(SELECT COUNT(DISTINCT SOMEOTHERVALUE) FROM MYOTHERTABLE) as theOtherCount
FROM RDB$DATABASE
CTE per table + cross join
WITH query1 AS (
SELECT
SUM(ID) as theSum,
COUNT(DISTINCT SOMEVALUE) as theCount
FROM MYTABLE
),
query2 AS (
SELECT
COUNT(DISTINCT SOMEOTHERVALUE) as theOtherCount
FROM MYOTHERTABLE
)
SELECT
query1.theSum,
query1.theCount,
query2.theOtherCount
FROM query1
CROSS JOIN query2
There are probably some more solutions. You might want to ask yourself if it is worth the effort of coming up with a (convoluted, hard to understand) single query to get this data were two queries are sufficient, easier to understand and in the case of large datasets: two separate queries might be faster.
In this case all "count" would return the same value.
Try to do the same using sub queries:
Select
(Select count (*) from Table1),
   (Select count (*) from table2)
from Table3

How to compare two rows in SQL Server

I'm used to mysql when you can do that with no problems. I would like to run the following statement in SQL Server however it doesn't see the column C_COUNT.
SELECT
A.customers AS CUSTOMERS,
(SELECT COUNT(ID) FROM Partners_customers B WHERE A.ID = B.PIID) AS C_COUNT
FROM Partners A
WHERE CUSTOMERS <> [C_COUNT]
Is it possible to utilize any mathematical operations in the SELECT area like
SELECT (CUSTOMERS - C_COUNT) AS DIFFERENCE
SQL Server does not allow you to use aliases in the WHERE clause. You'll have to have something like this:
SELECT *, Customers - C_COUNT "Difference"
FROM (
SELECT
A.customers AS CUSTOMERS,
(SELECT COUNT(ID)
FROM Partners_customers B WHERE A.ID = B.PIID)
AS C_COUNT FROM Partners A
) t
WHERE CUSTOMERS <> [C_COUNT]
Or, better yet, eliminating an inline count:
select A.customers, count(b.id)
FROM Partners A
LEFT JOIN Partners_customers B ON A.ID = B.PIID
Group By A.ID
having a.customers <> count(b.id)
WITH A AS
(
SELECT
A.customers AS CUSTOMERS,
(SELECT COUNT(ID) FROM Partners_customers B WHERE A.ID = B.PIID) AS C_COUNT
FROM Partners A
WHERE CUSTOMERS <> [C_COUNT]
)
SELECT
*,
(CUSTOMERS - C_COUNT) AS DIFFERENCE
FROM A
Completely untested....
(select * from TabA
minus
select * from TabB) -- Rows in TabA not in TabB
union all
(
select * from TabB
minus
select * from TabA
) -- rows in TabB not in TabA

SQL query to merge 2 tables with additional conditions?

I have 2 identical tables: user_id, name, age, date_added.
USER_ID column may contain multiple duplicate IDs.
Need to merge those 2 tables into 1 with the following condition.
If there are multiple records with identical 'name' for the same user then need to keep only the LATEST (by date_added) record.
This script will be used with MSSQL 2005, but would also appreciate if somebody comes up with version that does not use ROW_NUMBER(). Need this script to reload a broken table once, performance is not critical.
example:
table1:
1,'john',21,01/01/2010
1,'john',15,01/01/2005
1,'john',71,01/01/2001
table2:
1,'john',81,01/01/2007
1,'john',15,01/01/2005
1,'john',11,01/01/2008
result:
1,'john',21,01/01/2010
UPDATE:
I think that I've found my own solution. It is based on an answer for my previous question given by Larry Lustig and Joe Stefanelli.
with tmp2 as
(
SELECT * FROM table1
UNION
SELECT * FROM table2
)
SELECT * FROM tmp2 c1
WHERE (SELECT COUNT(*) FROM tmp2 c2
WHERE c2.user_id = c1.user_id AND
c2.name = c1.name AND
c2.date_added >= c1.date_added) <= 1
Could you please help me to convert this query to the one without 'WITH' clause?
Here's a variant of #Andomar's answer:
; with all_users as
(
select *
from table1 u1
union all
select *
from table2 u2
)
, ranker as (
select *,
rank() over (partition by userid order by recordtime) as [r]
)
select * from ranker where [r] = 1
Just in the interests of giving a different approach...
WITH distinctlist
As (SELECT user_id,
name
FROM table1
UNION
SELECT user_id,
name
FROM table2)
SELECT C.*
FROM distinctlist d
CROSS APPLY (SELECT TOP 1 *
FROM (SELECT TOP 1 *
FROM table1
WHERE user_id = d.user_id
AND name = d.name
ORDER BY date_added DESC
UNION ALL
SELECT TOP 1 *
FROM table1
WHERE user_id = d.user_id
AND name = d.name
ORDER BY date_added DESC) T
ORDER BY date_added DESC) C
You could use not exists, like:
; with all_users as
(
select *
from table1 u1
union all
select *
from table2 u2
)
select *
from all_users u1
where not exists
(
select *
from all_users u2
where u1.name = u2.name
and u1.record_time < u2.record_time
)
If the database doesn't support CTE's, expand all_users in the two places it is used.
P.S. If there are only three columns, and no more, you could use an even simpler solution:
select name
, MAX(record_time)
from (
select *
from table1 u1
union all
select *
from table2 u2
) sub
group by
name