Check If table partition exists for date - sql-server

I have created a partition function on a table: BIZ_DATE_TRADE_PF().
The column I specify to create the function is a business date for example: 20220616.
I have a java application, that needs to check existence of this partition for a given business date before executing the ALTER statement that modifies the partition using the current business date:
ALTER PARTITION FUNCTION BIZ_DATE_TRADE_PF() SPLIT RANGE (:bizDate)
I can check for the existence of this partition by name by querying SELECT * FROM SYS.partition_functions but how do I check current partition exists for the given business date, already created or not?

WITH T AS
(
SELECT *, $PARTITION.BIZ_DATE_TRADE_PF('20220616') AS "PARTITION"
FROM ??? AS f --> the partitionned table
)
SELECT T.*, fs.name AS FILEGROUP_NAME,
f.name AS FILE_NAME,
f.physical_name
FROM T
JOIN sys.partitions AS p
ON p.object_id = OBJECT_ID('???') --> the partitionned table
AND T."PARTITION" = p.partition_number
AND index_id = 0
JOIN sys.allocation_units AS au
ON p.hobt_id = au.container_id
JOIN sys.filegroups AS fs
ON au.data_space_id = fs.data_space_id
JOIN sys.database_files AS f
ON fs.data_space_id = f.file_id;

Related

how to use aggregate query result as column in another query having joins using stored procedures in SQL Server

i have a inner join query in stored procedure which is working fine. i need to inject a aggregate query in it so that it show an aggregated result in a new column
https://drive.google.com/file/d/1tAIEACvEnG7sAisSoE2crYRrzCjIcvST/view?usp=sharing
i tried to inject aggregate query as a column TotalQty in my query
SELECT dbo.SO.Id,dbo.Customer.Name, dbo.Product.Name AS ProductName, dbo.SOD.SalePrice
,TotalQty = (select SUM(dbo.SOD.Quantity) from [sod] o where o.SOId='68BD0F69-B957-439F-9AD0-180DF23EF42B' )
FROM dbo.SOD INNER JOIN
dbo.Product ON dbo.SOD.ProductId = dbo.Product.Id RIGHT JOIN
dbo.SO ON dbo.SOD.SOId = dbo.SO.Id INNER JOIN
dbo.Customer ON dbo.SO.CustomerId = dbo.Customer.Id
WHERE (dbo.SO.Id = '68BD0F69-B957-439F-9AD0-180DF23EF42B')
But it says
Column 'dbo.SO.Id' is invalid in the select list because it is not
contained in either an aggregate function or the GROUP BY clause.
or any other good Technique suggested will be appreciated.
so change AS :
SELECT dbo.SO.Id,dbo.Customer.Name, dbo.Product.Name AS ProductName, dbo.SOD.SalePrice
,(select count(dbo.SOD.Quantity) from [sod] o where o.SOId='68BD0F69-B957-439F-9AD0-180DF23EF42B') AS TotalQty
FROM dbo.SOD INNER JOIN
dbo.Product ON dbo.SOD.ProductId = dbo.Product.Id RIGHT JOIN
dbo.SO ON dbo.SOD.SOId = dbo.SO.Id INNER JOIN
dbo.Customer ON dbo.SO.CustomerId = dbo.Customer.Id
WHERE (dbo.SO.Id = '68BD0F69-B957-439F-9AD0-180DF23EF42B')
As in the internal query, your characteristic is you used the o.SOId field on where and in other hand used count aggregate function so you should:
SELECT dbo.SO.Id,dbo.Customer.Name, dbo.Product.Name AS ProductName,
dbo.SOD.SalePrice
,count(dbo.SOD.Quantity) AS TotalQty
FROM dbo.SOD INNER JOIN
dbo.Product ON dbo.SOD.ProductId = dbo.Product.Id RIGHT JOIN
dbo.SO ON dbo.SOD.SOId = dbo.SO.Id INNER JOIN
dbo.Customer ON dbo.SO.CustomerId = dbo.Customer.Id
WHERE (dbo.SO.Id = '68BD0F69-B957-439F-9AD0-180DF23EF42B')
group by
dbo.SO.Id,dbo.Customer.Name, dbo.Product.Name , dbo.SOD.SalePrice
Which will have the same output.
Generally speaking, you encourage others to help if you provide a MVCE. Using cryptic table names (are they tables? or views perhaps?) is not a healthy practice. In addition, it is not clear what you are trying to achieve with your subquery. You attempted to use count but you label the value as "TotalQty" and you replied to a suggestion using "sum". Very confusing.
So since we don't have your tables, I used the common MS sample database AdventureWorks. Below are two examples of counting the quantity values from the detail table.
select Ord.SalesOrderID, Det.SalesOrderDetailID,
Cust.AccountNumber as CustName, -- too lazy to get actual name
Prd.Name as ProductName,
Det.UnitPrice
,Counted.TotalQty
-- TotalQty = (select count(dbo.SOD.Quantity) from [sod] o where o.SOId='68BD0F69-B957-439F-9AD0-180DF23EF42B' )
from Sales.SalesOrderHeader as Ord
inner join Sales.SalesOrderDetail as Det on Ord.SalesOrderID = Det.SalesOrderID
inner join Production.Product as Prd on Det.ProductID = Prd.ProductID
inner join Sales.Customer as Cust on Ord.CustomerID = Cust.CustomerID
cross apply (select count(DetCnt.OrderQty) as TotalQty from Sales.SalesOrderDetail as DetCnt where DetCnt.SalesOrderID = Det.SalesOrderID) as Counted
where Ord.SalesOrderID = 43659
select Ord.SalesOrderID, Det.SalesOrderDetailID,
Cust.AccountNumber as CustName, -- too lazy to get actual name
Prd.Name as ProductName,
Det.UnitPrice
, TotalQty = (select count(DetCnt.OrderQty) from Sales.SalesOrderDetail as DetCnt where DetCnt.SalesOrderID = Det.SalesOrderID)
-- TotalQty = (select count(dbo.SOD.Quantity) from [sod] o where o.SOId='68BD0F69-B957-439F-9AD0-180DF23EF42B' )
from Sales.SalesOrderHeader as Ord
inner join Sales.SalesOrderDetail as Det on Ord.SalesOrderID = Det.SalesOrderID
inner join Production.Product as Prd on Det.ProductID = Prd.ProductID
inner join Sales.Customer as Cust on Ord.CustomerID = Cust.CustomerID
where Ord.SalesOrderID = 43659
I think that interpretation is correct but I don't know your schema. I added the PK of the detail table to help "see" the relationship between Order and Detail.
Examine the code closely. Notice how the query only refers to the specific PK value once (this would be your procedure's parameter). You use correlations and joins to limit the results as needed. And notice how much easier it is to understand the query since it uses names that are actual words - SalesOrder vs. SO. I don't think it makes much sense to right join your Detail table to the Order table - seems like a mistake. Your aggregation attempt is odd so I can't say if the value computed by these queries is correct.
I'll also note that you should not be passing the PK value of your table using a nvarchar parameter. Use the correct datatype to avoid the possibility that someone attempts to pass an actual string (e.g., N'Pick me') instead of a GUID value.

Find computed columns in SQL Server views

A colleague asked me to help them to identify the views in a database that have one or more computed columns. The database has hundreds of views so they're trying to find an automated way to accomplish this task. I am not seeing the results in the database that I was expecting. Here is an example:
--DROP TABLE dbo.Products
CREATE TABLE dbo.Products
(
ProductID int IDENTITY (1,1) NOT NULL
, QtyAvailable smallint
, UnitPrice money
);
--DROP VIEW dbo.uvw_Products
CREATE VIEW dbo.uvw_Products
AS
SELECT ProductID
, QtyAvailable
, UnitPrice
, (QtyAvailable * UnitPrice) AS InventoryValue
FROM dbo.Products;
-- Look at the view and find the computed column
SELECT OBJECT_SCHEMA_NAME(T.[object_id],DB_ID()) AS [Schema],
T.[name] AS [table_name], AC.[name] AS [column_name],
TY.[name] AS system_data_type, AC.[max_length],
AC.[precision], AC.[scale], AC.[is_nullable], AC.[is_ansi_padded], AC.[is_computed]
FROM sys.[views] AS T
INNER JOIN sys.[all_columns] AC ON T.[object_id] = AC.[object_id]
INNER JOIN sys.[types] TY ON AC.[system_type_id] = TY.[system_type_id] AND AC.[user_type_id] = TY.[user_type_id]
WHERE T.[is_ms_shipped] = 0
AND T.[name] = 'uvw_Products'
ORDER BY T.[name], AC.[column_id]
-- Pulls up no results - no entries in sys.computed_columns
SELECT TOP 10 *
FROM sys.computed_columns C
INNER JOIN sys.views V ON C.[object_id] = V.[object_id]
WHERE V.[name] = 'uvw_Products'
As you can see from this simple example, SQL Server does not seem to be storing the value in the is_computed column.
What am I missing? How can we find the computed columns in views?
I know it's not ideal, I don't think a fool-proof solution exists for this problem, but depending on your naming conventions you could do a join to the tables sys view on column names so see which columns exist and don't exist in there.
for example:
SELECT v.*
FROM
(
SELECT [Schema] = OBJECT_SCHEMA_NAME(t.[object_id], DB_ID())
, [table_name] = t.[name]
, [column_name] = vc.[name]
FROM sys.[views] t
JOIN sys.[all_columns] vc ON t.[object_id] = vc.[object_id]
) v
LEFT JOIN
(
SELECT [Schema] = OBJECT_SCHEMA_NAME(t.[object_id], DB_ID())
, [table_name] = t.[name]
, [column_name] = vc.[name]
FROM sys.[tables] t
JOIN sys.[all_columns] vc ON t.[object_id] = vc.[object_id]
) t
ON t.[column_name] = v.[column_name]
WHERE t.[table_name] IS NULL
Returns:
Schema | table_name | column_name
----------------------------------------
dbo | uvw_Products | InventoryValue
And if your views contain the source table in its name like 'uvw_Products' you could also use that in your join to avoid columns in other tables getting in the way.
Again its not ideal but a relatively simple solution to narrow the search

T-SQL join table in where exists

I have the below query
select *
from monthly_accounts m
join blocks_Dep on (m.code = d.code )
where exists (select R_code
from balance c
inner join blocks_div d on (m.b_id = d.b_id and c.name = d.name)
)
I am getting an error about an invalid m.b_i identifier; how to make join between the first table and tables in exists with the join?
Maybe you are getting that error because the operator is exists not exist. Does this work?
select m.*, d.*
from monthly_accounts m join
blocks_Dep d
on m.code = d.code
where exists (select 1
from balance b inner join
blocks_div bd
on b.name = bd.name
where m.b_id = bd.b_id
);
Note that I made other changes and fixed other problems:
blocks_dep did not have a table alias.
I assigned table aliases that are abbreviations of the table names for all tables.
I moved the correlation clause to a where rather than the on. I don't expect to see correlation clauses in an on (although the logic is correct).
You have some answers
The core should stand on it's own
Use alias and don't repeat the alias
select * from
monthly_accounts m
join blocks_Dep on (m.code=d.code)
d is not yet defined. Even the query parser figured it out I doubt that is what you wanted.
This links the not exists by m.b_id which is what I think you mean to do?
select *
from monthly_accounts m
join blocks_Dep d1
on m.code = d1.code
where not exists ( select 1
from balance c
join blocks_div d2
on d2.b_id = m.b_id
and d2.name = c.name
)

Return Stored Procedures, tables and columns in reference to a particular database

I am looking to write a query that will return all of the stored procedures and views that reference a specific database that I am looking to rebuild. I also need the query to return the columns and table names that the returned stored procedures / views contain in reference to the database being rebuilt.
I have a query right now that will return the stored procs and views, but have been unsuccessful in returning the column and table names that reference the database.
SELECT Distinct so.Name, so.type--, sc.text
FROM sysobjects so(NOLOCK)
INNER JOIN syscomments sc (NOLOCK) on so.Id = sc.ID
WHERE so.Type in( 'p' , 'v')
AND sc.Text LIKE '%membership_dw.%'
ORDER BY so.Name
Membership_DW is the name of the database where the stored procedures and views are currently stored, and it is also the database that is being recreated.
Here is a quick and dirty query to do it
;WITH cte as(
select *
from sys.sysdepends t1
inner join sys.objects t2 on t1.depid = t2.object_id
where t2.type = 'U' and is_ms_shipped = 0)
SELECT t5.name as SP_NAME, t6.name as TBL_NAME, t9.name COLNAME from sys.objects t5
INNER JOIN cte t6 on t6.id = t5.object_id
INNER JOIN sys.columns t9 on t6.object_id = t9.object_id
where t5.is_ms_shipped = 0 and t6.name not like 'sys%'
order by sp_name, TBL_NAME

How do I name the results of a joined table query

I have two tables and did an inner join on them based on id. Now I need to name this joined table. How do I do that? The reason I want to name this table is because I have to join this result table with some other tables.
You created what is commonly referred t as a relvar, not another table. You can join to it by placing it's SELECT definition in a sub query like this:
SELECT
FROM (
-- original join SQL
) t
INNER JOIN table2 on ...
You can create an alias for the result of a join using a subquery. For example:
select *
from (
select *
from tbl1
join tbl2
on tbl1.id = tbl2.id
) as JoinAlias
join tbl3
on JoinAlias.id = tbl3.id
You can often make do without such an alias. For example, consider a third join:
select *
from tbl1
join tbl2
on tbl1.id = tbl2.id
join tbl3
on tbl3.col1 = tbl1.col1
and tbl3.col2 = tbl2.col2
As you can see, the third join's condition can refer to columns from all earlier tables.
select * from (
select * from TableA a join TableB b on a.id = b.a_id
) as p;
As per the comments, it seems that a view might be what you are looking for:
create view MyView
as
select * from TableA a join TableB b on a.id = b.a_id;
It won't be listed in the tables (rather in the views), but will behave just like a table in your sql editor.

Resources