Build Dynamic SQL with Joins on multiple keys - sql-server

I want to build a dynamic query where all the data points are stored in a table.
e.g.
Declare #Load varchar(2000) = 'Id,CategoryID,SubcatID'
I need the below output:
on b.id = b2.id and b.CategoryID = b2.CategoryID and b.SubcatID = b2.SubcatID
where b.id is null and b.CategoryID is null and b.SubcatID is null

I was able to accomplish the task
Thanks
SELECT *
, 'b.'+Value Sources
, 'b2.'+Value Destination
, 'b.'+Value +'='+ 'b2.'+Value JoinCondition
, 'b2.'+Value + ' IS NULL ' JoinFilters
into #temp
FROM dbo.Split(#IncrementalLoad,',')
SELECT STRING_AGG(JoinCondition, ' and ') AS JoinCondition
, STRING_AGG(JoinFilters, ' and ') AS JoinFilters
from #temp

Related

Create postgres view from table with dynamic casting

I want to create a generic query that will allow me to create a view (from a table) and convert all Array columns into strings.
Something like:
CREATE OR REPLACE VIEW view_1 AS
SELECT *
for each column_name in columns
CASE WHEN pg_typeof(column_name) == TEXT[] THEN array_to_string(column_name)
ELSE column_name
FROM table_1;
I guess that I can do that with stored procedure but I'm looking for solution in pure SQL, if it can be to much complex.
Here is a query to do such conversion. You can then customize it to create the view and execute it.
SELECT
'CREATE OR REPLACE VIEW my_table_view AS SELECT ' || string_agg(
CASE
WHEN pg_catalog.format_type(pg_attribute.atttypid, pg_attribute.atttypmod) LIKE '%[]' THEN 'array_to_string(' || pg_attribute.attname || ', '','') AS ' || pg_attribute.attname
ELSE pg_attribute.attname
END, ', ' ORDER BY attnum ASC)
|| ' FROM ' || min(pg_class.relname) || ';'
FROM
pg_catalog.pg_attribute
INNER JOIN
pg_catalog.pg_class ON pg_class.oid = pg_attribute.attrelid
INNER JOIN
pg_catalog.pg_namespace ON pg_namespace.oid = pg_class.relnamespace
WHERE
pg_attribute.attnum > 0
AND NOT pg_attribute.attisdropped
AND pg_namespace.nspname = 'my_schema'
AND pg_class.relname = 'my_table'
; \gexec
Example:
create table tarr (id integer, t_arr1 text[], regtext text, t_arr2 text[], int_arr integer[]);
==>
SELECT id, array_to_string(t_arr1) AS t_arr1, regtext, array_to_string(t_arr2) AS t_arr2, int_arr FROM tarr;

SQL Server build dynamic sql

I have a temp table called #temp, and I need to get all the CDate column from that table, to build a string.
The CDate list in that table is (20171209, 20171210....20171223)
I expected to see
'A.[20171209] as [20171209], A.[20171210] as [20171210],
A.[20171211] as [20171211], A.[20171212] as [20171212],
A.[20171213] as [20171213], A.[20171214] as [20171214],
A.[20171215] as [20171215], A.[20171216] as [20171216],
A.[20171217] as [20171217], A.[20171218] as [20171218],
A.[20171219] as [20171219], A.[20171220] as [20171220],
A.[20171221] as [20171221], A.[20171222] as [20171222],
A.[20171223] as [20171223], '
however the result I got is missing the first date , ie 'A.[20171209] as [20171209]'
Here is my code:
SELECT
#col2 = ISNULL(#col2 + 'A.' + QUOTENAME(CDate) + ' as ' + QUOTENAME(CDate) + ', ' , '')
FROM
(SELECT DISTINCT CDate FROM #temp) AS tmp;
Your current approach will not work in some cases, it is an undocumented feature, always use For Xml path to concatenating the rows into csv.
SET #col2 = stuff((SELECT ', A.' + Quotename(CDate) + ' as '
+ Quotename(CDate)
FROM (SELECT DISTINCT CDate
FROM #temp) a
FOR xml path('')),1,1,'')

Microsoft SQL Server Rows to Column Transpose using PiVOT

I'm using MS-SQLServer-2016 and got a requirement to transpose rows to columns.
I'm using Pivot and dynamic SQL option to do it because the number of rows is dynamic.
Figure1 is the output I'm currently getting. However the client doesn't want those NULLs displayed. He only wants the Not-Null dates to be displayed.
Is there way to get rid of those Null Values and display only distinct dates?
Figure1-Transpose_Output
With Regards,
Tanuja
DECLARE #columns AS NVARCHAR(MAX), #sql AS NVARCHAR(MAX), #var1 AS
VARCHAR(MAX);
SELECT #columns = stuff((select DISTINCT ',' + quotename(replace(replace(replace(n.action_note,' ','<>'),'><',''),'<>',' ') )
from engagement_action n, action_party m, personal p
where n.action_id = m.action_id
and p.party_id = m.party_id
and n.action_note like 'XXX'
and m.system_name = 'XXXXXXXXXXXX'
and p.customer_number = 'XXXXXXX' FOR XML PATH(''),TYPE).value('.','NVARCHAR(MAX)'),1,1,'')
SELECT #sql =
'select "RANK_IN_PROP" ,
customer_number,
customer_shortname,
system_name,
'+ #columns + '
from
(SELECT RANK() OVER (PARTITION BY convert(date,m.created_when) ORDER BY convert(date,m.created_when))"RANK_IN_PROP" ,
p.customer_number,
p.customer_shortname,
m.system_name,
m.created_when ,
convert(date,m.created_when) as created_when,
replace(replace(replace(n.action_note,'' '',''<>''),''><'',''''),''<>'','' '') as action_note1
FROM engagement_action n, action_party m, personal p
WHERE n.action_id = m.action_id
AND p.party_id = m.party_id
AND n.action_note like ''%XXX%''
AND m.system_name = ''XXXXXXXXXXX''
AND p.customer_number = ''XXXXXXXX'' ) d
PIVOT
(max(created_when) for action_note1 in ( ' + #columns + ' ))p order by created_when desc'
execute(#sql);`
Can you try this , just added (select distinct action_note engagement_action where action_note is not null) in where clause. As i can't create test data so could not really execute the query
SELECT #columns = stuff((select DISTINCT ',' +
quotename(replace(replace(replace(n.action_note,' ','<>'),'><',''),'<>',' ')
)
from
(select distinct action_note engagement_action where action_note is not null)
n, action_party m, personal p
where n.action_id = m.action_id
and p.party_id = m.party_id
and n.action_note like 'XXX'
and m.system_name = 'XXXXXXXXXXXX'
and p.customer_number = 'XXXXXXX' FOR XML PATH(''),TYPE).value('.','NVARCHAR(MAX)'),1,1,'')

sql ssrs how to match variable to table parameter

I have a report that requires a parameter which may have one value, or a collection of values (jurisdictions assigned to a district office). I can't figure out how to ask sql if a particular value (a.jurisdiction) matched to a value contained in a parameter set up as a table. I have the following code:
DECLARE #District INT = 1614 --Richmond D1
DECLARE #StartDate DATETIME = '20160101'
DECLARE #EndDate DATETIME = '20160731'
DECLARE #Jurisdiction TABLE(Location INT) --= 1223 --Richmond City --multiselect?
IF #District = 1614 --Richmond District 1
INSERT INTO #Jurisdiction Values (1223); --Richmond City
IF #District = 1632 --Newport News District 19
INSERT INTO #Jurisdiction Values (1203); --Newport News
IF #District = 1642 --Fairfax District 29
INSERT INTO #Jurisdiction Values (2568) --Fairfax City
,(1154) ,(1140) ,(1178) ,(1243)
SELECT b.OffenderId
, b.Sex
, b.CurrentLocationId
, b.MasterTermId
, b.ReleaseDate
, b.Jurisdiction
, b.HomePlanAddress
FROM (SELECT DISTINCT o.OffenderId
, o.CurrentLocationId
, CASE WHEN o.GenderId = 12 THEN 'M'
WHEN o.GenderId = 13 THEN 'F'
ELSE 'Unknown' END AS Sex
, mt.MasterTermId
, t.TermId
, CASE WHEN t.GtrdApprovedDate IS NULL AND
t.MprdApprovedDate IS NULL THEN '19000101'
WHEN t.GtrdApprovedDate IS NULL THEN t.MprdApprovedDate
WHEN t.MprdApprovedDate IS NULL THEN t.GtrdApprovedDate
WHEN t.MprdApprovedDate < t.GtrdApprovedDate THEN
t.MprdApprovedDate
ELSE t.GtrdApprovedDate END AS ReleaseDate
, j.HomePlanAddress
, j.Jurisdiction
FROM ind.Offender AS o
INNER JOIN (SELECT oa.OffenderId
, oa.AddressId
, LTRIM(COALESCE(CAST(a.StreetNumber AS
VARCHAR(10)),' ') + COALESCE(a.StreetNumberSuffix
+ ' ',' '
+ COALESCE(a.StreetName + ',','') + COALESCE(' '
+ a.AppartmentNumber + ',','')
+ l.LocationName + ',' + 'VA ' + COALESCE
(a.ZipCode,'')) AS HomePlanAddress
, j.LocationName AS Jurisdiction
FROM ind.Offender_Address AS oa
INNER JOIN ref.Address AS a ON oa.AddressId =
a.AddressId
LEFT JOIN ref.Location AS l ON a.CountyId = l.LocationId
INNER JOIN ref.Location AS j ON a.JurisdictionId = j.LocationId
WHERE a.StateId = 1047
AND EXISTS (SELECT a.JurisdictionId FROM #Jurisdiction)
--AND a.JurisdictionId IN (#Jurisdiction) --
AND oa.AddressTypeId = 5 --Proposed
AND oa.EndDate IS NULL) AS j ON o.OffenderId = j.OffenderId
INNER JOIN scl.MasterTerm AS mt ON o.OffenderId = mt.OffenderId
LEFT JOIN scl.Term AS t ON mt.MasterTermId = t.MasterTermId
WHERE o.CurrentLocationId IS NOT NULL
AND t.TermStatusId <> 631) AS b --Inactive
WHERE b.ReleaseDate BETWEEN #StartDate AND #EndDate
I've tried to find solutions, but most of them refer to using stored procedures, which I can't use in our environment. I tried the EXISTS option on one answer I found, but it gives me all locations, not just the ones in the parameter. Any suggestions?
The reference to the answer SSRS Multiple Value parameter filter based on dataset doesn't seem to address the fact that the District parameter has no one-on-one match to the values used for Jurisdiction. But it gives me something to work on and play around with.
I don't know why
AND a.JurisdictionId IN (#Jurisdiction)
doesn't work for you. As far as I can tell it should.
You can try adding the Filter to the SSRS dataset instead of inside the query. Choose your Jurisdiction for the Expression and your Jurisdiction Parameter as the value.

vb table adapter does not allow more than one parameter in the IN clause

What I need to achieve is to send a list of unknown QTY of values to a Sql server NOT IN clause but can only achieve this with singular values. below is my Sql statement:
SELECT SorMaster.LastInvoice
, SorMaster.SalesOrder
, SorMaster.OrderStatus
, ArCustomer.RouteCode
, SorMaster.Customer
, SorMaster.CustomerName
, SorMaster.CustomerPoNumber
, SorMaster.OrderDate
, SorMaster.DateLastInvPrt
, ArInvoice.InvoiceBal1
, ArInvoice.TermsCode
FROM SorMaster AS SorMaster
INNER JOIN ArCustomer AS ArCustomer ON SorMaster.Customer = ArCustomer.Customer
INNER JOIN ArInvoice AS ArInvoice ON SorMaster.LastInvoice = ArInvoice.Invoice
WHERE (SorMaster.OrderStatus = '9')
AND (SorMaster.Branch LIKE 'J%')
AND (SorMaster.DocumentType = 'O')
AND (SorMaster.LastInvoice > #Last_Invoice)
AND (SorMaster.OrderDate > DATEADD(Month, - 4, GETDATE()))
AND (SorMaster.LastInvoice NOT IN (#ExclusionList))
ORDER BY SorMaster.LastInvoice
The #ExclusionList value is generated by this code as a string from a listbox:
Dim exclusion As String = ""
If MenuForm.ExclusionCB.Checked = True Then
For i = 0 To MenuForm.ExclusionLB.Items.Count - 2
exclusion = exclusion & MenuForm.ExclusionLB.Items(i) & ","
Next
exclusion = exclusion & MenuForm.ExclusionLB.Items(MenuForm.ExclusionLB.Items.Count - 1)
Else
exclusion = ""
End If
I have also tried sending the entire listbox as a collection.
Does anyone know how I can send more than one value (something like 1,2,3,4,5,6) and have sql understand that these is more than one? I won't have an issue with the SELECT statement changing, just as long as it returns the same information.
The reason I need this with the exception list, is our remote DB PK is on the Salesorder column and the local DB is on the LastInvoice column
Hope this makes sense. if you need more info, please let me know
You can send it as a string and use dynamic sql. Here's a simple example how to do that.
DECLARE #vals VARCHAR(50) = '1,2,3,4,5,6'
DECLARE #sql VARCHAR(MAX) = 'SELECT * FROM TABLE WHERE FIELD1 IN'
SET #sql = #sql + ' (' + #vals + ')'
-- #sql = 'SELECT * FROM TABLE WHERE FIELD1 IN (1,2,3,4,5,6)'
EXEC (#sql)

Resources