SQL multiple tables reach - sql

I have this chunk of code here, thing is it query selected "TestLog" and shows:
name,
schema,
rowcount,
totalspace,
usedspace,....
Thing is I need this information to be queried for more than one table, lets say a 5 specific ones... can anyone help out?
USE myDB
GO
SELECT
t.name AS TableName,
s.name AS SchemaName,
p.rows AS RowCounts,
SUM(a.total_pages) * 8 / 1024 AS TotalSpaceMB,
SUM(a.used_pages) * 8 / 1024 AS UsedSpaceMB,
(SUM(a.total_pages) - SUM(a.used_pages)) * 8 / 1024 AS UnusedSpaceMB
FROM
sys.tables t
INNER JOIN sys.indexes i ON t.object_id = i.object_id
INNER JOIN sys.partitions p ON i.object_id = p.object_id AND i.index_id = p.index_id
INNER JOIN sys.allocation_units a ON p.partition_id = a.container_id
LEFT OUTER JOIN sys.schemas s ON t.schema_id = s.schema_id
WHERE
t.name = ('TestLog')
AND t.is_ms_shipped = 0
AND i.object_id > 255
GROUP BY
t.name, s.name, p.rows
ORDER BY
t.name;
GO

It works as below:
-- specific tables
WHERE
t.name in ('Test1' , 'Test2' , 'Test3')
AND t.is_ms_shipped = 0
AND i.object_id > 255
-- one specific table
WHERE
t.name = 'TestLog'
AND t.is_ms_shipped = 0
AND i.object_id > 255
-- specific tables with test in front
WHERE
t.name like 'Test%'
AND t.is_ms_shipped = 0
AND i.object_id > 255

Related

SQL: count and show all rows and columns of all tables under a scheme

somewhere on the net (source missing, may be here) I got this SQL-statement:
SELECT t.NAME AS TableName, SUM(a.total_pages) * 8 AS TotalSpaceKB, p.Rows FROM sys.tables t
INNER JOIN sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN sys.allocation_units a ON p.partition_id = a.container_id
LEFT OUTER JOIN sys.schemas s ON t.schema_id = s.schema_id
WHERE t.NAME NOT LIKE 'dt%' AND t.NAME LIKE '%MY_TABLES%' AND s.Name LIKE 'MY_ACHEMA'
AND t.is_ms_shipped = 0
AND i.OBJECT_ID > 255
GROUP BY t.Name, p.Rows
ORDER BY p.Rows DESC
which gives me a beautiful view with 3 columns. something like this:
TableName TotalSpaceKB Rows
TABLE 3231656 76000
TABLE 2305632 29136
TABLE 2213128 14160
TABLE 1954200 3020
etc...
now I'd like to expand it to inclide the number of columns of each table. How can this be done?
I removed the grouping and used subqueries:
SELECT
t.NAME AS TableName,
(SELECT SUM(a.total_pages) * 8
FROM sys.indexes i
INNER JOIN sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN sys.allocation_units a ON p.partition_id = a.container_id
WHERE t.OBJECT_ID = i.object_id AND i.OBJECT_ID > 255
) AS TotalSpaceKB,
(SELECT SUM(p.Rows)
FROM sys.indexes i
INNER JOIN sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
WHERE t.OBJECT_ID = i.object_id AND i.OBJECT_ID > 255
) AS Rows,
(SELECT COUNT(*) FROM sys.columns c WHERE t.OBJECT_ID = c.object_id) AS Columns
FROM sys.tables t
LEFT OUTER JOIN sys.schemas s ON t.schema_id = s.schema_id
WHERE t.NAME NOT LIKE 'dt%' AND t.NAME LIKE '%MY_TABLES%' AND s.Name LIKE 'MY_ACHEMA'
AND t.is_ms_shipped = 0
ORDER BY Rows DESC
This should work for you by adding in the INFORMATION_SCHEMA.COLUMNS.
SELECT t.NAME AS TableName, SUM(a.total_pages) * 8 AS TotalSpaceKB, p.Rows, COUNT(COLUMN_NAME) AS ColumnCount
FROM sys.tables t
INNER JOIN sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN sys.allocation_units a ON p.partition_id = a.container_id
LEFT JOIN sys.schemas s ON t.schema_id = s.schema_id
LEFT JOIN INFORMATION_SCHEMA.COLUMNS ISC ON t.NAME = ISC.TABLE_NAME
WHERE t.NAME NOT LIKE 'dt%' AND t.NAME LIKE '%MY_TABLES%' AND s.Name LIKE 'MY_ACHEMA'
AND t.is_ms_shipped = 0
AND i.OBJECT_ID > 255
GROUP BY t.Name, p.Rows
ORDER BY p.Rows DESC

Metadata of Getting number of rows in Views

How come is it not possible to return number of rows in a View using sys.views in the below query while using sys.table you can
SELECT t.NAME AS table_name,
s.name AS owner,
p.[Rows] as NUM_ROWS,
FROM sys.tables t INNER JOIN
sys.indexes i
ON t.OBJECT_ID = i.object_id INNER JOIN
sys.partitions p
ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id inner join
sys.schemas s on s.schema_id = t.schema_id
WHERE t.NAME NOT LIKE 'dt%' AND i.OBJECT_ID > 255 AND
i.index_id <= 1 /* AND
s.name in ('Schemaname1','Schemaname2') */
GROUP BY t.NAME, i.object_id, i.index_id, i.name,s.name, p.[Rows]
ORDER BY object_name(i.object_id) ;
Its a syntax issue you got, an extra comma in the query after NUM_ROWS ?
SELECT t.NAME AS table_name,
s.name AS owner,
p.[Rows] as NUM_ROWS /*, remove this comma*/
FROM sys.tables t INNER JOIN
sys.indexes i
ON t.OBJECT_ID = i.object_id INNER JOIN
sys.partitions p
ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id inner join
sys.schemas s on s.schema_id = t.schema_id
WHERE t.NAME NOT LIKE 'dt%' AND i.OBJECT_ID > 255 AND
i.index_id <= 1 /* AND
s.name in ('Schemaname1','Schemaname2') */
GROUP BY t.NAME, i.object_id, i.index_id, i.name,s.name, p.[Rows]
ORDER BY object_name(i.object_id) ;

sql one specific table size and stats

i have this fine working query for determining
size,rowcount,ununsed,total mb of db..
it is mssql
thing is is there a way to modify this so it does query only one specific table in DB ? thanks alot. also any hints on how can i query more statistics ? thanks
USE [mydbname]
GO
SELECT
s.Name AS SchemaName,
t.Name AS TableName,
p.rows AS RowCounts,
CAST(ROUND((SUM(a.used_pages) / 128.00), 2) AS NUMERIC(36, 2)) AS Used_MB,
CAST(ROUND((SUM(a.total_pages) - SUM(a.used_pages)) / 128.00, 2) AS NUMERIC(36, 2)) AS Unused_MB,
CAST(ROUND((SUM(a.total_pages) / 128.00), 2) AS NUMERIC(36, 2)) AS Total_MB
FROM sys.tables t
INNER JOIN sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN sys.allocation_units a ON p.partition_id = a.container_id
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
GROUP BY t.Name, s.Name, p.Rows
ORDER BY s.Name, t.Name
GO
You should just add the where condition:
WHERE t.Name = 'TABLE_NAME_GOES_HERE'
And if you have same tables in different schemas
WHERE t.Name = 'TABLE_NAME_GOES_HERE' and s.Name = 'SCHEMA_NAME_GOES_HERE'
okay finally a solution.
USE db_name
GO
SELECT
t.name AS TableName,
s.name AS SchemaName,
p.rows AS RowCounts,
SUM(a.total_pages) * 8 AS TotalSpaceKB,
SUM(a.used_pages) * 8 AS UsedSpaceKB,
(SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB
FROM
sys.tables t
INNER JOIN sys.indexes i ON t.object_id = i.object_id
INNER JOIN sys.partitions p ON i.object_id = p.object_id AND i.index_id = p.index_id
INNER JOIN sys.allocation_units a ON p.partition_id = a.container_id
LEFT OUTER JOIN sys.schemas s ON t.schema_id = s.schema_id
WHERE
t.name = 'table_name'
AND t.is_ms_shipped = 0
AND i.object_id > 255
GROUP BY
t.name, s.name, p.rows
ORDER BY
t.name;
GO

Multiple tables with the same name in SQL Server

when running the query below, I get a duplicate table returned, even though only one of it exists. Why could that be?
SELECT
s.Name AS SchemaName,
t.NAME AS TableName,
p.rows AS RowCounts,
SUM(a.total_pages) * 8 AS TotalSpaceKB,
SUM(a.used_pages) * 8 AS UsedSpaceKB,
(SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB
FROM
sys.tables t
INNER JOIN
sys.schemas s ON s.schema_id = t.schema_id
INNER JOIN
sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN
sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN
sys.allocation_units a ON p.partition_id = a.container_id
WHERE
t.NAME NOT LIKE 'dt%'
AND t.is_ms_shipped = 0
AND i.OBJECT_ID > 255
GROUP BY
t.Name, s.Name, p.Rows
ORDER BY
TotalSpaceKB DESC
** UPDATE
The database name was displayed with a (In Recovery) tag, I just ran a script to check and it said that it is 11% completed. Could this also have caused this problem?
As Sean pointed out, you have more than one index on the duplicated tables. To check the index name(s) you can run the slightly modified query:
SELECT
t.NAME AS TableName,
s.Name AS SchemaName,
p.rows AS RowCounts,
i.name,
SUM(a.total_pages) * 8 AS TotalSpaceKB,
SUM(a.used_pages) * 8 AS UsedSpaceKB,
(SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB
FROM
sys.tables t
INNER JOIN
sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN
sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN
sys.allocation_units a ON p.partition_id = a.container_id
LEFT OUTER JOIN
sys.schemas s ON t.schema_id = s.schema_id
WHERE
t.NAME NOT LIKE 'dt%'
AND t.is_ms_shipped = 0
AND i.OBJECT_ID > 255
GROUP BY
t.Name, s.Name, p.Rows, i.name
ORDER BY
t.name

Count(*) differs from rows in sys.partitions

I'm using the following query to get information about all tables in a DB:
SELECT
t.NAME AS TableName,
i.name as indexName,
sum(p.rows) as RowCounts,
sum(a.total_pages) as TotalPages,
sum(a.used_pages) as UsedPages,
sum(a.data_pages) as DataPages,
(sum(a.total_pages) * 8) / 1024 as TotalSpaceMB,
(sum(a.used_pages) * 8) / 1024 as UsedSpaceMB,
(sum(a.data_pages) * 8) / 1024 as DataSpaceMB
FROM
sys.tables t
INNER JOIN
sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN
sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN
sys.allocation_units a ON p.partition_id = a.container_id
WHERE
t.NAME NOT LIKE 'dt%' AND
i.OBJECT_ID > 255 AND
i.index_id <= 1
GROUP BY
t.NAME, i.object_id, i.index_id, i.name
ORDER BY
object_name(i.object_id)
The problem is that for some tables it reports a different row count than if I do:
select count(*) FROM someTable
Why is that?
Edit:
The first query returns a higher count:
First: 1 240 464
Second: 413 496
The problem is that there's more than one allocation_unit per partition, so the same partition can appear more than once and therefore the sum(p.rows) ends up counting the same partition more than once, so you get a multiple of the right number of rows.
Here's how I solved the problem:
(note that my query isn't identical to yours, I have slightly different columns and used Kb rather than Mb, but the idea is the same)
SELECT
s.Name + '.' + t.name AS table_name,
(select sum(p2.rows)
from sys.indexes i2 inner join sys.partitions p2 ON i2.object_id = p2.OBJECT_ID AND i2.index_id = p2.index_id
where i2.object_id = t.object_id and i2.object_id > 255 and (i2.index_id = 0 or i2.index_id = 1)
) as total_rows,
SUM(CASE WHEN (i.index_id=0) OR (i.index_id=1) THEN a.total_pages * 8 ELSE 0 END) AS data_size_kb,
SUM(CASE WHEN (i.index_id=0) OR (i.index_id=1) THEN a.used_pages * 8 ELSE 0 END) AS data_used_kb,
SUM(CASE WHEN (i.index_id=0) OR (i.index_id=1) THEN 0 ELSE a.total_pages * 8 END) AS index_size_kb,
SUM(CASE WHEN (i.index_id=0) OR (i.index_id=1) THEN 0 ELSE a.used_pages * 8 END) AS index_used_kb,
SUM(a.total_pages) * 8 AS total_size_kb,
SUM(a.used_pages) * 8 AS total_used_kb,
SUM(a.used_pages) * 100 / CASE WHEN SUM(a.total_pages) = 0 THEN 1 ELSE SUM(a.total_pages) END AS percent_full
FROM
sys.tables t
INNER JOIN
sys.schemas s ON s.schema_id = t.schema_id
INNER JOIN
sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN
sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN
sys.allocation_units a ON p.partition_id = a.container_id
WHERE
t.is_ms_shipped = 0 AND i.OBJECT_ID > 255
GROUP BY
t.object_id, t.Name, s.Name
ORDER BY SUM(a.total_pages) DESC
From the sys.partitions documentation
rows bigint Approximate number of rows in this partition.
(emphasis mine). The system views aren't going to keep a spot-on number of rows in the table. Think of what that would entail and how much overhead it would add to all insert/delete statements. If I were a betting man, I'd say that it's doing something with the count of the number of pages in the clustered index or heap which is a far cheaper operation. That's purely speculative, though.
Have you looked into the help article regarding the sys.allocation_units view? Apparently, the container_id field is a little more than it seems. Try to add this to the where section:
and a.type = 2
In SQL Server 2016, To fix the count(*) and sys.partitions mismatch I performed an Index Rebuild on the Primary Key. Luckily the TABLE only had 2.4 million rows so it didn't take that long as I have standard edition so couldn't do the rebuild ONLINE.
Inner joins will cause unmatched rows to be filtered out. Groups will also affect your row counts as they can combine rows. These two conditions were cause a lower row count for the aggregate query than the simple count(*).
I see specifically you're asking about the sys.partitions table. The likely explanation is that there is not a match for every row in the sys.indexes table given the match condition of i.object_id = p.OBJECT_ID AND i.index_id = p.index_id. Try running this:
Select
count(*)
from
sys.partitions p
LEFT JOIN
sys.indexes i ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
You will then likely see the count you expect. Remove the count function to simply Select * ... to find the unmatched rows.