SQL Server: Modifying this query - sql

This query gives me all the information that I need, however I'm wanting to display it differently if possible. The current result: http://i.imgur.com/BFKGFSx.jpg
DECLARE #MainHospital varchar(50)='HOSPITAL 1';
SELECT MainEmail, chkOutpatient, chkPartB
FROM SurveyPicList
WHERE MainHospital = #MainHospital
GROUP BY MainHospital, MainEmail, chkOutpatient, chkPartB
I'm trying to return 2 different list of MainEmail comma-delimited if they = "on" in chkOutpatient and chkPartB. So only 2 cells of data as a result. 1 header of chkOutpatient with a list of comma dilmeted emails that = "on", and 1 header of chkPartB with the same.
So for chkPartB, something like this?http://i.imgur.com/RFlV24Q.jpg
SELECT DISTINCT ', ' + MainEmail AS chkPartB
FROM SurveyPicList
WHERE MainHospital = #MainHospital
AND chkPartB = 'on'
Please let me know if my question is unclear or if I need to give more info.

WITH Outpatients AS (
SELECT DISTINCT MainEmail
FROM SurveyPicList
WHERE MainHospital = #MainHospital
AND chkOutpatient = 'on'
)
,OutpatientsRawCsv AS (
SELECT (
SELECT ',' + MainEmail
FROM Outpatients
FOR XML PATH('')
) AS Csv
)
,PartBs AS (
SELECT DISTINCT MainEmail
FROM SurveyPicList
WHERE MainHospital = #MainHospital
AND chkPartB = 'on'
)
,PartBRawCsv AS (
SELECT (
SELECT ',' + MainEmail
FROM PartBs
FOR XML PATH('')
) AS Csv
)
SELECT STUFF(OutpatientsRawCsv.Csv, 1, 1, '') AS OutpatientsCsv
,STUFF(PartBRawCsv.Csv, 1, 1, '') AS PartBCsv
FROM OutpatientsRawCsv
CROSS JOIN PartBRawCsv

Related

SQL HIVE Conversion

I'm trying to convert a piece of SQL code to HiveQL, and it's not working as expected.
Please find below the code snippet in SQL that I'm attempting to convert:
SQL Code:
UPDATE
C
SET
C.prod_l = P.prod_l, C.numprod = P.numprod, C.prod_cng = P.prod_cng
FROM
[cnc].dbo.[c_cnc_analysis] C
LEFT JOIN
(
SELECT
X.*,
Len(prod_l) - Len(Replace(prod_l, ' ~ ', ' ')) + 1 AS NumProd,
CASE
WHEN
Len(prod_l) - Len(Replace(prod_l, ' ~ ', ' ')) + 1 = 1
THEN
0
ELSE
1
END
AS PROD_CNG
FROM
(
SELECT DISTINCT
ST2.uitid,
Substring((
SELECT
' ~ ' + ST1.product_id AS [text()]
FROM
(
SELECT
[uitid],
[product_id]
FROM
dbo.[c_cnc_dedup_bse]
GROUP BY
[uitid],
[product_id]
)
ST1
WHERE
ST1.uitid = ST2.uitid
ORDER BY
ST1.uitid FOR xml path ('')), 4, 1000 ) [PROD_L]
FROM
(
SELECT
[uitid],
[product_id]
FROM
dbo.[c_cnc_dedup_bse]
GROUP BY
[uitid],
[product_id]
)
ST2
)
X
)
P
ON C.uitid = P.uitid;
Converted HIVE Query:
create
or replace view prd_temp as
SELECT
`UITID`,
`PRODUCT_ID`
FROM
`C_CNC_DEDUP_BSE`
GROUP BY
`UITID`,
`PRODUCT_ID`;
create
or replace view prd_temp2 as
SELECT
`UITID`,
`PRODUCT_ID`
FROM
`C_CNC_DEDUP_BSE`
GROUP BY
`UITID`,
`PRODUCT_ID`;
create
or replace view prd_temp3 as
SELECT
st1.`uitid`,
concat(' ~ ', st1.`PRODUCT_ID`) AS `text()`
FROM
prd_temp ST1
left join
prd_temp2 st2
on ST1.`UITID` = ST2.`UITID`
where
st1.`UITID` = st2.`UITID`
ORDER BY
ST1.`UITID`;
create
or replace view prd_temp4 as
SELECT
st1.`uitid`,
concat_ws('''', `text()`)
FROM
prd_temp3 ST1
ORDER BY
ST1.`UITID`;
create
or replace view st2 as
SELECT DISTINCT
`UITID`,
SUBSTRING(`_c1` , 4, 1000) as `PROD_L`
FROM
prd_temp4;
create
or replace view x as
SELECT
*,
LENGTH(PROD_L) - LENGTH(REPLACE(PROD_L, ' ~ ', ' ')) + 1 as NumProd,
CASE
WHEN
LENGTH(PROD_L) - LENGTH(REPLACE(PROD_L, ' ~ ', ' ')) + 1 = 1
then
0
ELSE
1
END
as PROD_CNG
from
ST2;
create table C_CNC_ANALYSIS1 as
select
c.*,
P.numprod as numprod,
p.prod_cng as prod_cng,
p.prod_l as prod_l
from
`C_CNC_ANALYSIS` C
LEFT JOIN
X P
ON C.UITID = P.UITID ;
SELECT
*
from
c_cnc_analysis1 limit 100;
Appreciate all the help with this. I think the code converted for the XML path is not working in HIVE, since I'm getting multiple UITIDs (key) and the information in separate rows rather than just one single record per UITID.
Thank You,
Viswanath Sitaraman

Concatenate column values based on type result

Declare #name nvarchar(max),#Id int
SELECT #Id=[EmpType],#name =ISNULL(#name + ',','')+[UserName] FROM [dbo].[TestTable]
Group by [EmpType]
SELECT #Id,#name
Getting error with this code, How can i get the result employee type wise concatenated usernames
Expecting Result set
You can try below using STUFF() function
SELECT [EmpType], abc = STUFF(
(SELECT ',' + [UserName]
FROM [dbo].TestTable] t1
WHERE t1.[EmpType] = t2.[EmpType]
FOR XML PATH (''))
, 1, 1, '') from [dbo].TestTable] t2
group by [EmpType];

SQL Server convert xml to csv using CTE - nulls currently being ignored

I am using CTE to convert xml to csv so that it can be exported to a file, however if I have an empty xml tag, this currently gets ignored.
Here is my initial solution courtesy of this previous very helpful post:
https://stackoverflow.com/a/23785202/6260721
Here is my sql:
CREATE TABLE EXPORT_TEST
(
DATA varchar(max)
)
INSERT INTO EXPORT_TEST (DATA)
VALUES ('<EXPORT_DATA><ID>ABC123</ID><PRICE_A>5.6</PRICE_A><PRICE_B></PRICE_B><PRICE_C>8.1</PRICE_C></EXPORT_DATA>')
DECLARE #commaSeparatedValues NVARCHAR(MAX)
DECLARE #xml XML = (SELECT TOP 1 CONVERT(xml,DATA) FROM EXPORT_TEST)
;WITH cte AS (
SELECT
rownr = ROW_NUMBER() OVER (ORDER BY #commaSeparatedValues),
Tbl.col.query('.') AS [xml]
FROM #xml.nodes('EXPORT_DATA') Tbl(col)
), cols AS (
SELECT
rownr,
Tbl.Col.value('.', 'nvarchar(max)') AS Value
FROM cte
CROSS APPLY cte.xml.nodes('//text()') Tbl(Col)
)
INSERT INTO EXPORT_TEST(DATA)
SELECT DISTINCT
STUFF((
SELECT ',' + IIF(ISNUMERIC(value) = 1, Value, '''' + Value + '''')
FROM cols SSF WHERE SSF.rownr = S.rownr
FOR XML PATH(''),TYPE
).value('.','VARCHAR(MAX)'
), 1, 1, '') as DATA
FROM cols S
SELECT * FROM EXPORT_TEST
At the moment, it is returning:
'ABC123',5.6,8.1
But I don't want it to ignore PRICE_B, I want it to return an empty string:
'ABC123',5.6,,8.1 <--extra comma required where PRICE_B should be
How can I achieve this?
Besides the possibility to shredd the full XML and re-concatenate its values (there is an answer already), you might use FLWOR-XQuery:
DECLARE #xml XML=
'<EXPORT_DATA>
<ID>ABC123</ID>
<PRICE_A>5.6</PRICE_A>
<PRICE_B />
<PRICE_C>8.1</PRICE_C>
</EXPORT_DATA>';
EDIT better to read with a variable $txt instead of ($n/text())[1]
SELECT
STUFF
(
#xml.query('
let $r:=/EXPORT_DATA
for $n in $r/*
let $txt:=($n/text())[1]
return if(empty($txt) or not(empty(number($txt)))) then
concat(",",string($txt))
else concat(",''",string($txt),"''")
').value('.','nvarchar(max)'),1,1,'');
The result
'ABC123' ,5.6 , ,8.1
This code works on a mass of records using XQUERY.
I'm assuming char(10) (Line Feed) does not appear in your data.
I'm assuming the maximum length of the concatenated text is 1000 (I don't want to use varchar(max) for no good reason)
You can change both of these assumptions if you wish
declare #separator char(1) = char(10)
select substring
(
replace
(
cast
(
cast(DATA as xml).query
(
'for $i in //*
where not($i/*)
return concat
(
sql:variable("#separator")
,if(local-name($i) = "ID") then ('''''''') else ('''')
,($i/text())[1]
,if(local-name($i) = "ID") then ('''''''') else ('''')
)'
) as nvarchar(1000)
) ,' ' + #separator ,','
) ,2 ,1000
) as csv
from EXPORT_TEST
INSERT INTO EXPORT_TEST (DATA) VALUES
('<EXPORT_DATA><ID>ABC123</ID><PRICE_A>5.6</PRICE_A><PRICE_B></PRICE_B><PRICE_C>8.1</PRICE_C></EXPORT_DATA>')
,('<EXPORT_DATA><ID>DEF456</ID><PRICE_A>6.7</PRICE_A><PRICE_B>66.77</PRICE_B><PRICE_C>7.2</PRICE_C></EXPORT_DATA>')
,('<EXPORT_DATA><ID>GHI789</ID><PRICE_A></PRICE_A><PRICE_B>88.99</PRICE_B><PRICE_C></PRICE_C></EXPORT_DATA>')
csv
'ABC123',5.6,,8.1
'DEF456',6.7,66.77,7.2
'GHI789',,88.99,
What about this:
;WITH cte AS (
SELECT
rownr = ROW_NUMBER() OVER (ORDER BY #commaSeparatedValues),
Tbl.col.query('.') AS [xml]
FROM #xml.nodes('EXPORT_DATA') Tbl(col)
), cols AS (
SELECT
rownr,
Tbl.Col.value('.', 'nvarchar(max)') AS Value
FROM cte
CROSS APPLY cte.xml.nodes('EXPORT_DATA/child::node()') Tbl(Col)
)
INSERT INTO EXPORT_TEST(DATA)
SELECT DISTINCT
STUFF((
SELECT ',' + IIF(ISNUMERIC(value) = 1 OR LEN(value) = 0, Value, '''' + Value + '''')
FROM cols SSF WHERE SSF.rownr = S.rownr
FOR XML PATH(''),TYPE
).value('.','VARCHAR(MAX)'
), 1, 1, '') as DATA
FROM cols S
Using cte.xml.nodes('EXPORT_DATA/child::node()') in the second CTE will give as all nodes:
;WITH cte AS (
SELECT
rownr = ROW_NUMBER() OVER (ORDER BY #commaSeparatedValues),
Tbl.col.query('.') AS [xml]
FROM #xml.nodes('EXPORT_DATA') Tbl(col)
)
SELECT
rownr
,Tbl.Col.query('.')
,Tbl.Col.value('.', 'nvarchar(max)') AS Value
FROM cte
CROSS APPLY cte.xml.nodes('EXPORT_DATA/child::node()') Tbl(Col)
Then, in the concatenation we need to add check for empty string:
IIF(ISNUMERIC(value) = 1 OR LEN(value) = 0, Value, '''' + Value + '''')

Select statement within a select statement

I have the following select statement that returns exactly what I want:
DECLARE #result varchar(max) = ''
SELECT #result += (result.Fullname + '<br/>')
FROM (SELECT DISTINCT Fullname
FROM Providers
WHERE Status='A') as result
select substring(#result, 0, len(#result) - 4)
The only problem is, I want the output from this query to be displayed as a column entry from a larger select statement.
Eg.
SELECT
Column AS [AColumnName],
SELECT #result += (result.Fullname + '<br/>')
FROM (SELECT DISTINCT Fullname
FROM Providers
WHERE Status='A') as result
select substring(#result, 0, len(#result) - 4) as [LenderList]
FROM
Table
But I am currently getting the error: Incorrect syntax near the keyword 'SELECT'.
The error pointing to line 4
Any ideas?
You need aggregate string concatenation in SQL Server. There are already many answers on the subquery, but to save you the trouble:
SELECT Column AS [AColumnName],
STUFF((SELECT DISTINCT '<br/>' + Fullname
FROM Providers
WHERE Status = 'A'
FOR XML PATH (''), TYPE
).value('.', 'varchar(max)'
), 1, 5, ''
) as result
FROM Table;
The use of the type is important because your string has special XML characters.
Can you simply run it in 2 statements?
SELECT #result += (result.Fullname + '<br/>')
FROM (SELECT DISTINCT Fullname
FROM Providers
WHERE Status='A') as result
SELECT
Column AS [AColumnName],
substring(#result, 0, len(#result) - 4)
FROM Table
Which Database? If you can use for xml, then something like...
select substring(a.innards, 0, len(a.innards) - 4) as [LenderList]
from
(
SELECT innards = STUFF(
(SELECT DISTINCT Fullname + '</br>'
FROM Providers
WHERE [Status] = 'A'
FOR XML PATH(''), TYPE).value('.[1]', 'nvarchar(max)')
, 1
, 0
, '')
) a

How to combine two rows with comma separator in sql server 2008

I tried as shown below
SELECT SUBSTRING(
(
SELECT td.Text + ', ' AS 'data()',
Tda.FirmID
FROM tblData1 tda
INNER JOIN tblData2 Td
ON Tda.ID = Td.ID
GROUP BY
Tda.Enable1,
Tda.ID,
Td.Text
HAVING ISNULL(Enable1, 0) = 1
FOR XML PATH('')
),
1,
10000
) AS Csv
Output:
Landlord Tenant, <FirmID>1</FirmID>NJ Traffic, <FirmID>1</FirmID>
Expected Output: Should be in table format
csv FirmID
Landlord Tenant, NJ Traffic 1
I got the results by using COALESCE
DECLARE #Text VARCHAR(MAX)
DECLARE #ID NUMERIC(18,0)
SELECT #Text = COALESCE(#Text + ', ', '') +
CAST(td.Text AS VARCHAR(MAX)),#ID = MAX(tda.FirmID)
FROM tblData1 tda
INNER JOIN tblData2 Td
ON Tda.ID=Td.ID
GROUP BY
Tda.Enable,
Tda.FirmID,Td.Text
HAVING ISNULL(Enable,0)=1
SELECT #Text AS Text,#ID AS ID
OutPut:
text ID
Landlord Tenant, NJ Traffic 1
Leave out the aliases in the subquery and try this:
SELECT STUFF((SELECT ', ' + td.Text
FROM tblData2 Td
WHERE ISNULL(Enable1, 0) = 1
FOR XML PATH('')
), 1, 2, '') AS Csv,
MAX(Tda.FirmID)
FROM tblData1 tda;
You cannot select multiple columns in the subquery either. After all, the purpose is to combine values into a single column. Multiple values in the select create one column, but with multiple XML tags within the string.
You also do not need the group by in the subquery.