Using SQLite I can get all tablenames in my database:
SELECT name AS Tablename FROM sqlite_master WHERE type = 'table'
Result will be some tablenames, for example:
Tablename:
cars
planes
bus
How could I have a SQL query that will count the number of records for each table that is found, result should be:
Tablename Records:
cars 100
planes 200
bus 300
I understand that in this example I simply could run 3 SELECT COUNT() statements, however the number of tables can vary so that I can not hardcode a fixed number of SELECT COUNT()
All table and column names in a statement need to be known at the time it is compiled, so you can't do this dynamically.
You'd have to programmatically build up a new query string based on the results of getting the table names from sqlite_master. Either one query per table like you mentioned, or all together by creating something that looks like
SELECT 'table1' AS Tablename, count(*) AS Records FROM table1
UNION ALL
SELECT 'table2', count(*) FROM table2
-- etc.
You don't mention what language you're working in, so in psuedo-code of a functional style:
var allcounts = query("SELECT name FROM sqlite_master WHERE type = 'table'")
.map(name -> "SELECT '$name' AS Tablename, count(*) AS Records FROM \"$name\"")
.join(" UNION ALL ");
var totals = query(allcounts);
Related
I am trying to get the number of columns in a row for a given table in teradata. I am finding it difficult to find the total number with the usual SQL command. This is what I have tried but did not give me any result:
SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_catalog = 'WMS'
AND table_name = 'RM_SELLER_ITEM_MST'
INFORMATION_SCHEMA is not implemented in Teradata, the DBC database holds metadata:
SELECT COUNT(*)
FROM dbc.ColumnsV
WHERE DatabaseName = 'WMS'
AND TableName = 'RM_SELLER_ITEM_MST'
Assume the two tables reside in the same file. So the question is, other than their names, are the tables identical, i.e., same schema, same contents.
To compare the table schemas, look at the statements in the sqlite_master table:
SELECT sql FROM sqlite_master WHERE tbl_name IN ('This', 'That');
You have to ignore the table name itself in the comparison; automatic replacement is harder if you have any column names or comments that containt the table name.
To compare the contents, just use compound queries to check whether there are any rows that are not in the other table:
SELECT NOT EXISTS (SELECT * FROM This
EXCEPT
SELECT * FROM That)
AND NOT EXISTS (SELECT * FROM That
EXCEPT
SELECT * FROM This);
I believe that the following may suffice :-
/*
Compare Schema and data in tables.
t1 is the SQL for the first table (mytable) with the table name changed to a common name (table)
t2 is the SQL for the second table (mytable_copy1) with the table changed to a common name (table)
(so if t1 and t2 are equal then the schema is the same)
tablecompare is the logical result of comparing the data of each table with the other table
except matching rows so if no rows exists then NOT EXISTS will be true (1) AND the two
and the result will be 1 if both tables exactly match each other.
*/
SELECT
(t1 = t1) AND tablecompare AS test FROM
(SELECT
replace(sql,'mytable','table') AS t1, -- change the table name to a common name
replace(sql,'mytable_copy1','table') AS t2, -- change the table name to a common name
(
SELECT NOT EXISTS (SELECT * FROM mytable EXCEPT SELECT * FROM mytable_copy1)
AND NOT EXISTS (SELECT * FROM mytable_copy1 EXCEPT SELECT * FROM mytable)
) AS tablecompare
FROM sqlite_master WHERE name = 'mytable'
)
Note the tables are mytable and mytable_copy1 so these would be changed to reflect the two tables.
Perhaps less confusing (perhaps more) is this more long-winded solution :-
/*
Table Compare
t1 is the SQL for the first table (mytable) with the table name replace by table
t2 is the SQL for the second table (mytable_copy1) again table name change to table
So if t1 = t2 then the schema is identical
t1count is the number of rows in the first table
t2count is the number of rows in the second table
So if the counts are the same then the tables may be identical
unioncount is the count of the union of the two tables (not union all) so duiplicates are dropped
therefore if unioncount is the same as either of the table counts then tables are identical
NOTE!!! this assumes tables are not WITHOUT ROWID tables (would have to omit the inclusion of rowid NOT TESTED)
the inclusion of rowid could be dropped (NOT TESTED) if there is an alias of rowid.
*/
SELECT
t1 = t1 AND t1count = t2count AND t1count = unioncount AS test FROM
(SELECT
replace(sql,'mytable','table') AS t1, -- change the table name to a common name
replace(sql,'mytable_copy1','table') AS t2, -- change the table name to a common name
(SELECT count() FROM mytable) AS t1count, -- get the number of rows
(SELECT count() FROM mytable_copy1) AS t2count, -- get the number of rows
(SELECT count() AS unioncount FROM
(SELECT rowid,* FROM mytable UNION SELECT rowid,* FROM mytable_copy1)) AS unioncount
FROM sqlite_master WHERE name = 'mytable'
) ;
Both solutions return a single row/column result 1 if the tables match 0 if they do not.
It could however, but less time consuming/resource hungry to do individual tests. e.g. if the schema's don't match do nothing otherwise check the row counts and if they don't match don't do the final check of actually checking the data.
Test the following tables were used for testing :-
For mytable and mytable_copy1 :-
The above both produced 1 as per :-
and :-
When the following table (mytable_copy2 with changed data highlighted) :-
The results were :-
and :-
I am passing datatable as input parameter to stored procedure. Datatable contains id, Name,Lname,Mobileno,EmpId.
Employee table contains [Name],[Lname],[mobno],[Did] as columns.
When user is logged in, his Id come as DId. There are more than 1000 records. Instead of passing that id to datatable, I have created
separete parameter to sp. I want to add records to Employee table, which are not already exist. If combination of mobileno and Did already exists, then
don't insert into Employee table, else insert. Datatable may contain records, which can be duplicate. So I don't want to include that record. I want select only
distinct records and add them to table. I am intrested in mobile no. If there are 10 record having same moble no, I am fetching record, which comes first.
Following code is right or wrong. According to my knowledge, first from clause, then inner join, then where, then select execute. Record get fetched from datatable,
then inner join happens generate result, from that result not from datatable it will check record. So it will give me proper output.
Create Procedure Proc_InsertEmpDetails
#tblEmp EmpType READONLY,
#DId int
as
begin
INSERT INTO Employee
([Name],[Lname],[mobno],[Did])
SELECT [Name],[Lname],[mobno] #DId
FROM #tblEmp A
Inner join (
select min(Id) as minID, mobno from #tblEmp group by mobno
) MinIDTbl
on MinIDTbl.minID = A.ExcelId
WHERE NOT EXISTS (SELECT 1
FROM Employee B
WHERE B.[mobno] = A.[mobno]
AND B.[Did] = #DId )
end
or does I need to change like this
INSERT INTO Employee
([Name],[Lname],[mobno],[Did])
SELECT C.[Name],C.[Lname],C.[mobno], C.D_Id
from
(SELECT [Name],[Lname],[mobno] #DId as D_Id
FROM #tblEmp A
Inner join (
select min(Id) as minID, mobno from #tblEmp group by mobno
) MinIDTbl
on MinIDTbl.minID = A.ExcelId
)C
WHERE NOT EXISTS (SELECT 1
FROM Employee B
WHERE B.[mobno] = C.[mobno]
AND B.[Did] = #DId )
I have 2 tables, one is indexing the other.
I am querying Table#1, and it has one column (string) that has an ID in it that corresponds to a unique row in Table#2. Im trying to write a query in Sqlite that allows me to retrieve the value from Table#2 if the column value in Table#1 is not an empty string.
Kinda like:
"SELECT TMake,TModel,TTrim,IYear,[%q] AS TPart1 FROM AppGuide WHERE TPart1 != ''"
But instead of retrieving the Index value (TPart1) Id like to get the string from Table#2.
Is this possible?
Any help is appreciated.
You could use a correlated subquery:
SELECT TMake,
TModel,
...,
(SELECT stringvalue
FROM Table2
WHERE Table2.ID = Table1.TPart1)
FROM Table1
WHERE Table1.TPart1 != ''
However, these are rather slow to execute, so you'd better use a join (this returns exactly the same result):
SELECT Table1.TMake,
Table1.TModel,
...,
Table2.stringvalue
FROM Table1 LEFT JOIN Table2 ON Table1.TPart1 = Table2.ID
WHERE Table1.TPart1 != ''
If you don't want to get records from Table1 that have no matching Table2 record, drop the LEFT.
I am trying to do an SQL query on two tables to retrieve multiple columns with a certain column (PostID) to be distinct (and it is not the primary key of the that table).
In addition, I need the selected distinct rows to be the latest (one of the columns retrieved is the entry date).
Detailed description:
I am building a forum like application, using 3 tables to store data.
I use table1 to store user details, table2 to store the meta data for posts, table3 to store the post details, updates, and replies (postID is unique in table2 pointing towards an original post, while in table3, it is used to show the original post and updates and replies).
Table columns:
table1 (UserID, FullName, mobile, etc.)
table2 (postID, UserID, EntryDate, Deleted columns)
table3 (postdetailsId, PostID, UserID, Entrydate, etc.)
I am trying to retrieve all the posts for 1 user in a gridview, my SQL query uses the USERID to retrieve all his posts from the table. However, it is retrieving the original post and all its updates, and I only want to retrieve the latest update of each post.
How can it be done fully in SQL (I know I can do it in C# with the returned results)?
My query:
SELECT T1.FullName, T3.PostID, T3.EntryDate, T3.Title
FROM Table1 as T1, Table3 as T3
WHERE T3.UserID = T1.UserID
AND T3.UserID = #UserID
You could use GROUP BY PostID along with MAX(EntryDate)
SELECT *
FROM (
SELECT posts.*, ROW_NUMBER() OVER (PARTITION BY post_updates.UserID, post_updates.PostID ORDER BY post_updates.EntryDate DESC) AS rn
FROM table1 users
JOIN table3 post_updates
ON post_updates.userID = users.UserID
WHERE users.UserID = #UserID
) q
WHERE rn = 1