I have master table with several details tables. I need to check if each of the details tables have any rows for given ID. Right now I am going through all the tables and checking if count>0 but there must be a better way.
SELECT COUNT(*) FROM Table1 WHERE ID=3;
SELECT COUNT(*) FROM Table2 WHERE ID=3;
...
SELECT COUNT(*) FROM TableN WHERE ID=3;
Is there a way to do this in one effective SQL statement?
WITH CTE AS
(
SELECT 'T1' AS Name, COUNT(*) AS Total FROM Table1 WHERE ID=3
UNION ALL
SELECT 'T2' AS Name, COUNT(*) AS Total FROM Table2 WHERE ID=3
UNION ALL
...
UNION ALL
SELECT 'Tn' AS Name, COUNT(*) AS Total FROM TableN WHERE ID=3;
)
Select * from CTE where Total > 0
This sounds like poor design of your tables. I think you need to either combine some tables or add a bridge table that you can query.
Or, keep querying the individual tables if you structure is optimal and just have your application deal with running each one.
If you really want one result set you can do:
DECLARE #ID INT
SET #ID = 3
SELECT 'Table1' TableName, COUNT(*) FROM Table1 WHERE ID=#ID;
UNION
SELECT 'Table2' TableName, COUNT(*) FROM Table2 WHERE ID=#ID;
UNION
...
UNION
SELECT 'TableN' TableName, COUNT(*) FROM TableN WHERE ID=#ID;
I don't see a way to not scan all tables if that's what you're trying to avoid.
Related
I have a 'unique' column, 'GID_New' that is in multiple tables. Is there a way to check if it's unique across all the tables in the QGIS project in SQL?
Can it be done in one SQL search without merging the tables into one and then running something like
SELECT A.GID_New, count(*), A.TableName
FROM "Water_Merged" as A
Group by A.GID_New
And then checking for a count >1
I would like to know which table the non-unique GID_New's are from as well.
The data is in a geopackage in QGIS so the code needs to work in QGIS SQL implementation.
You can use union all:
select gid_new, count(*) no_matches
from (
select gid_new from table1
union all select gid_new from table2
union all select gid_new from table3
) t
group by gid
having count(*) > 1
If you want to know in which table duplicates exists, then one option is string concatenation. Assuming that your database uses string_agg(), that would look like:
select gid_new, count(*) no_matches, string_agg(which, ',') which_tables
from (
select 'table1' which, gid_new from table1
union all select 'table2', gid_new from table2
union all select 'table3', gid_new from table3
) t
group by gid
having count(*) > 1
I'm working on learning more about how the UNION function works in SQL Server.
I've got a query that is directed at a single table:
SELECT Category, COUNT(*) AS Number
FROM Table1
GROUP BY Category;
This returns the number of entries for each distinct line in the Category column.
I have multiple tables that are organized by this Category column and I'd like to be able to have the results for every table returned by one query.
It seems like UNION will accomplish what I want it to do but the way I've tried implementing the query doesn't work with COUNT(*).
SELECT *
FROM (SELECT Table1.Category
Table1.COUNT(*) AS Number
FROM dbo.Table1
UNION
SELECT Table2.Category
Table2.COUNT(*) AS Number
FROM dbo.Table2) AS a
GROUP BY a.Category
I'm sure there's an obvious reason why this doesn't work but can anyone point out what that is and how I could accomplish what I'm trying to do?
You cannot write a common Group by clause for two different select's. You need to use Group by clause for each select
SELECT TABLE1.Category, --missing comma here
COUNT(*) as Number -- Remove TABLE1. alias name
FROM dbo.TABLE1
GROUP BY Category
UNION ALL --UNION
SELECT TABLE2.Category, --missing comma here
COUNT(*) as Number -- Remove TABLE1. alias name
FROM dbo.TABLE2
GROUP BY Category
If you really want to remove duplicates in result then change UNION ALL to UNION
COUNT as any associated aggregation function has to have GROUP BY specified. You have to use group by for each sub query separately:
SELECT * FROM (
SELECT TABLE1.Category,
COUNT(*) as Number
FROM dbo.TABLE1
GROUP BY TABLE1.Category
UNION ALL
SELECT TABLE2.Category,
COUNT(*) as Number
FROM dbo.TABLE2
GROUP BY TABLE2.Category
) as a
It is better to use UNION ALL vs UNION - UNION eliminates duplicates from result sets, since - let say - you want to merge both results as they are it is safer to use UNION ALL
Is there a simpler way to count the number of rows in different tables that fulfill the same conditions?
For example, I want to separately count the number of rows in the following two tables that correspond to certain IDs:
Select
'table1' as tablename, count(*) as rownr from table1
where SOMEID in ('1815972751','1815751159','1815752967','1815756079')
union all
Select
'table2' as tablename, count(*) as rownr from table2
where SOMEID in ('1815972751','1815751159','1815752967','1815756079') ;
The result would be something like
table1 | 21
table2 | 54
However, I would like to only define the condition (in this case, the IDs) once, for example in a variable or list, so they area easily manageable.
Here is one way:
select tablename, count(*)
from (select 'table1' as tablename, someid
from table1
union all
select 'table2' as tablename, someid
from table2
) t
where someid in ('1815972751', '1815751159', '1815752967', '1815756079')
group by tablename;
Do note that performance may not be as good as in your original version.
I need to count rows in more than one table in SQL Server 2008. I do this:
select count(*) from (select * from tbl1 union all select * from tbl2)
But it gives me an error of incorrect syntax near ). Why?
PS. The actual number of tables can be more than 2.
In case you have different number of columns in your tables try this way
SELECT count(*)
FROM (
SELECT NULL as columnName
FROM tbl1
UNION ALL
SELECT NULL
FROM tbl2
) T
try this:
You have to give a name to your derived table
select count(*) from
(select * from tbl1 union all select * from tbl2)a
I think you have to alias the SELECT in the FROM clause:
select count(*)
from
(
select * from tbl1
union all
select * from tbl2
) AS SUB
You also need to ensure that the * in both tables tbl1 and tbl2 return exactly the same number of columns and they have to be matched in their type.
I don't like doing the union before doing the count. It gives the SQL optimizer an opportunithy to choose to do more work.
AlexK's (deleted) solution is fine. You could also do:
select (select count(*) from tbl1) + (select count(*) from tbl2) as cnt
I'm using a UNION and a LIMIT to select the earliest occurence of a type of table row from multiple tables. I need a record of which table satisfied the query in the result set.
Is there a way of doing something like:
SELECT id, someField, tableName FROM someUnknownTable WHERE someConditions = true
You can select your tableName as a constant value:
Select id, someField, 'Table1' As tableName
From table1
Union
Select id, someField, 'Table2' As tableName
From table2
The second alias (As tableName) can be omitted.