Create dynamic SQL based on column names passed through a string - join

I need to find out rows that are present in table A and missing from table B (using LEFT JOIN) wherein table A and table B are two tables with same structure but within different schema.
But the query has to be constructed using Dynamic SQL and the columns that need to be used for performing JOIN are stored in a string. How to extract the column names from string and use them to dynamically construct below query :
Database is Azure SQL Server
eg :
DECLARE #ColNames NVARCHAR(150) = 'col1,col2'
Query to be constructed based on columns defined in ColNames :-
SELECT *
FROM Table A
Left Join
Table B
ON A.col1 = B.col1
AND A.col2 = B.col2
AND B.col1 IS NULL AND B.col2 IS NULL
If the number of columns in #ColNames is more then the SELECT statement needs to cater for all the column.

Without knowing the full context, try this:
DECLARE #ColNames NVARCHAR(150) = 'col1,col2'
DECLARE #JoinContion NVARCHAR(MAX) = ''
DECLARE #WhereCondition NVARCHAR(MAX) = ''
SELECT #JoinContion += CONCAT('[a].', QUOTENAME(Value), ' = ', '[b].', QUOTENAME(Value), (CASE WHEN LEAD(Value) OVER(ORDER BY Value) IS NOT NULL THEN ' AND ' ELSE '' END))
,#WhereCondition += CONCAT('[a].', QUOTENAME(Value), ' IS NULL', (CASE WHEN LEAD(Value) OVER(ORDER BY Value) IS NOT NULL THEN ' AND ' ELSE '' END))
FROM STRING_SPLIT(#ColNames,N',')
SELECT #JoinContion, #WhereCondition
String_Split: To split the input string into columns
Lead: to determine if we need the AND keyword when it's not the last row.
Be aware the NOT EXISTS is probably a better solution then LEFT JOIN

Related

Solve the syntax error with Redshift operator does not exist and add explicit casts

I am a newbie in the area of redshift data modeling and got myself into trouble with an error.ERROR:
--Final version
syntax error ERROR: operator does not exist: text | record Hint: No
operator matches the given name and argument type(s). You may need to
add explicit type casts. Where: SQL statement "SELECT 'create temp
table ' || $1 || ' as select * from' | $2 |" PL/pgSQL function "egen"
line 36 at execute statement [ErrorId:
1-61dc32bf-0a451f5e2c2639235abb8876]
I am trying to do a simple transformation that gets returned in output when the procedure is called. (As of now I got to find from the documentation we have to use either temp table or cursors to achieve this)
Pseudocode:
I am trying to restrict data to its latest one in (2019) Get the
list of managers create columns if a person is a manager or not from the list.
Return it as a result
Data looks as follows Employee Data
My Select query works fine out of the procedure, please find my complete code below.
CREATE OR REPLACE PROCEDURE EGEN(tmp_name INOUT varchar(256) )
AS $$
DECLARE
--As i have less data managed to create it as an array or please use temp or table and join it with the actual query to perform transformation
MGR_RECORD RECORD;
DATAS RECORD;
item_cnt int := 0;
V_DATE_YEAR int := 0;
BEGIN
--EXECUTE (select cast(extract(year from current_date) as integer)-3) INTO V_DATE_YEAR;
--Manager Records are stored here below
SELECT DISTINCT managerid from "dev"."public"."emp_salary" INTO MGR_RECORD;
SELECT employeeid,
managerid,
promotion,
q_bonus,
d_salary,
case when contractor = 'x'
then 'TemporaryEmployee'
else 'PermanentEmployee'
END as EmployeeType,
-- IFstatement not supported under select query
case when employeeid in (select distinct managerid FROM "dev"."public"."emp_salary" )
then 'Manager'
else 'Ordinary FTE'
END as FTETYPE
FROM "dev"."public"."emp_salary" where cast(extract(year from promotion) as int ) >= 2019 into DATAS;
--COMMIT;
tmp_name := 'ManagerUpdatedTable';
EXECUTE 'drop table if exists ' || tmp_name;
EXECUTE 'create temp table ' || 'ManagerUpdatedTable' || ' as select * from' |DATAS| ;
END;
$$ LANGUAGE plpgsql;
-- Call tests CALL EGEN('myresult'); SELECT * from myresult;
Also, additional query (Can we replace )
case when employeeid in (select distinct managerid FROM "dev"."public"."emp_salary" )
then 'Manager'
else 'Ordinary FTE'
END as FTETYPE
this transform in query to IF , if possible please provide details.
Thanks and Regards,
Gabby

I have a stored procedure which returns Dynamic columns(using Pivot) I want to bind stored procedure with RDLC report

I want to create RDLC report ,but the problem is that Columns in a table returned by the stored procedure are Dynamic, means Columns can be increased or decrease depends on the condition.
I have Created procedure.
alter proc sp_GetEmpBranAndDesigWise(
#BranchId nvarchar(200),
#ZoneId nvarchar(200)
)
as
if 1=0 Begin
set FMTONLY OFF End
select b.BranchName,b.BranchCity,z.ZoneName,b.BranchID,d.DesigName
,Count(d.DesigName) as TotalCount
INTO #RepTablTemp
from Emp_File emp
INNER join Branch b on emp.BranchID=b.BranchID
left join ZoneFile z on z.ZoneID=b.ZoneID
INNER join SWHouse_Production.dbo.emp_DesigFile d on emp.DesigID=d.DesigID
where Convert(nvarchar(250), b.BranchID) like #BranchId
and Convert(nvarchar(250), b.ZoneID) like #ZoneId
group by b.BranchName,z.ZoneName,b.BranchCity,b.BranchID,d.DesigName
order by b.BranchName,z.ZoneName,d.DesigName
--select * from #RepTablTemp order by BranchName,DesigName
--select * from Emp_File where BranchID=1055
Begin
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(DesigName)
from #RepTablTemp
group by DesigName
--order by 1
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
print #cols
set #query = N'SELECT BranchName,ZoneName,BranchCity,' + ISNULL(#cols,'0') + N' from
(
select BranchName,ZoneName,BranchCity,TotalCount, DesigName
from #RepTablTemp
) x
pivot
(
max(TotalCount)
for DesigName in (' + #cols + N')
) p '
exec sp_executesql #query;
select 0 AS mycol1int
print #query
drop table #RepTablTemp
End
BranchName|ZoneName|BranchCity|Designation1|Designation2|Designation3
here Designations are dynamic and can be increased,i want this kind of result in RDLC
enter image description here
In attached file highlighted fields are Designations coming from Designation Table.
You can't do that. RDLC expects a fixed "object" for a table. You can pass a dynamic object, but this object must be match with the dataset provided to the table.
But you can use several tablix and show them or not (visibility condition) for an specific condition loaded by a parameter (for example, a kind of table do you want to see or hide).

Hive Join returning zero records

I have two Hive tables and I am trying to join both of them. The tables are not clustered or partitioned by any field. Though the tables contain records for common key fields, the join query always returns 0 records. All the data types are 'string' data types.
The join query is simple and looks something like below
select count(*) cnt
from
fsr.xref_1 A join
fsr.ipfile_1 B
on
(
A.co_no = B.co_no
)
;
Any idea what could be going wrong? I have just one record (same value) in both the tables.
Below are my table definitions
CREATE TABLE xref_1
(
co_no string
)
clustered by (co_no) sorted by (co_no asc) into 10 buckets
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
STORED AS TEXTFILE;
CREATE TABLE ipfile_1
(
co_no string
)
clustered by (co_no) sorted by (co_no asc) into 10 buckets
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
STORED AS TEXTFILE;
Hi You are using Star Schema Join. Please use your query like this:
SELET COUNT(*) cnt FROM A a JOIN B b ON (a.key1 = b.key1);
If still have issue Then use MAPJOIN:
set hive.auto.convert.join=true;
select count(*) from A join B on (key1 = key2)
Please see Link for more detail.

Generic procedure to delete duplicates - no PKs

I wrote a stored procedure with a table name as parameter, that checks if there are duplicate rows in this table. The statements are built dynamically of course:
INSERT INTO tmpTable
SELECT col1, col2,... FROM table GROUP BY col1, col2, ... HAVING COUNT(*) > 1;
DELETE FROM tablename FROM tablenname
INNER JOIN tmpTable ON ISNULL(tablename.col1, 0) = ISNULL(tmpTable.col1, 0)
AND ISNULL(tablename.col2, 0) = ISNULL(tmpTable.col2, 0)
AND ...;
INSERT INTO tablename SELECT * FROM tmpTable;
Should work so far, but problem is, that it fails when the table has blob columns, like text. Those can not be compared in the JOIN. I also tried
DELETE FROM tablename GROUP BY col1, col2, ... HAVING COUNT(*) > 1;
but GROUP BY is not supported in DELETE statement directly without self-joining.
Also it's not possible to query information_schema for primary key of this table, since none of these tables has one.
Any ideas? Thanks.
Since the statement is already built dynamically, add casting the relevant columns to varchar(max) for the purpose of join. It's not difficult to figure which columns that are:
select c.name, quotename(c.name, '[')
from
sys.columns c
inner join sys.types t on c.system_type_id = t.system_type_id
where
c.object_id = object_id(#TABLE_NAME)
and c.is_computed = 0
and t.name in ('text', 'image', 'timestamp', 'xml')

Find null values from table and replace it with space - sqlite

I am having sqlite database.
In some columns I am having null values.
I want to replace null values with space..
Is there any query for this?
Please let me know
Use IFNULL. In a query:
SELECT IFNULL(mycolumn, ' ') FROM mytable
Or to change the data in the table:
UPDATE mytable SET mycolumn = IFNULL(mycolumn, ' ')
Alternatively:
UPDATE mytable SET mycolumn = ' ' WHERE mycolumn IS NULL

Resources