SQL Query - not working as desired using openquery - sql-server-2008

I want to get the data for the previous day in the below query.
SELECT *
FROM OPENQUERY(SQL32BIT, 'SELECT DISTINCT * FROM OPENQUERY(SQL04, ''SELECT X.* FROM EMPLOYEES X WHERE X.E_JOINDATE = Curdate()'')')
GO

Try this:
Declare #MyQuery VARCHAR(4000),
#printed_datetime DateTime
SET #printed_datetime = DATEADD(dd, - 1, GETDATE())
SET #MyQuery ='SELECT DISTINCT * FROM OPENQUERY(SQL04,
''SELECT X.* FROM EMPLOYEES X WHERE X.E_JOINDATE =''''' + Convert(VarChar(20), #printed_datetime) + ''''''')';
exec(#MyQuery)

Related

Store values in different variables in SQL, separated by (Comma) ","

I need to separate values and store them in different variables in SQL,
for example
a='3100,3101,3102,....'
And the output should be
x=3100
y=3101
z=3102
.
.
.
create function [dbo].[udf_splitstring] (#tokens varchar(max),
#delimiter varchar(5))
returns #split table (
token varchar(200) not null )
as
begin
declare #list xml
select #list = cast('<a>'
+ replace(#tokens, #delimiter, '</a><a>')
+ '</a>' as xml)
insert into #split
(token)
select ltrim(t.value('.', 'varchar(200)')) as data
from #list.nodes('/a') as x(t)
return
end
GO
declare #cad varchar(100)='3100,3101,3102'
select *,ROW_NUMBER() over (order by token ) as rn from udf_splitstring(#cad,',')
token rn
3100 1
3101 2
3102 3
The results of the Parse TVF can easily be incorporated into a JOIN, or an IN
Declare #a varchar(max)='3100,3101,3102'
Select * from [dbo].[udf-Str-Parse](#a,',')
Returns
RetSeq RetVal
1 3100
2 3101
3 3102
The UDF if needed (much faster than recursive, loops, and xml)
CREATE FUNCTION [dbo].[udf-Str-Parse] (#String varchar(max),#Delimiter varchar(25))
Returns Table
As
Return (
with cte1(N) As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)),
cte2(N) As (Select Top (IsNull(DataLength(#String),0)) Row_Number() over (Order By (Select NULL)) From (Select N=1 From cte1 a,cte1 b,cte1 c,cte1 d) A ),
cte3(N) As (Select 1 Union All Select t.N+DataLength(#Delimiter) From cte2 t Where Substring(#String,t.N,DataLength(#Delimiter)) = #Delimiter),
cte4(N,L) As (Select S.N,IsNull(NullIf(CharIndex(#Delimiter,#String,s.N),0)-S.N,8000) From cte3 S)
Select RetSeq = Row_Number() over (Order By A.N)
,RetVal = LTrim(RTrim(Substring(#String, A.N, A.L)))
From cte4 A
);
--Orginal Source http://www.sqlservercentral.com/articles/Tally+Table/72993/
--Much faster than str-Parse, but limited to 8K
--Select * from [dbo].[udf-Str-Parse-8K]('Dog,Cat,House,Car',',')
--Select * from [dbo].[udf-Str-Parse-8K]('John||Cappelletti||was||here','||')
I suggest you to use following query, it's much faster than other functions like cross apply and udf.
SELECT
Variables
,S_DATA
FROM (
SELECT
Variables
,CASE WHEN LEN(LIST2)>0 THEN LTRIM(RTRIM(SUBSTRING(LIST2, NUMBER+1, CHARINDEX(',', LIST2, NUMBER+1)-NUMBER - 1)))
ELSE NULL
END AS S_DATA
,NUMBER
FROM(
SELECT Variables
,','+COMMA_SEPARETED_COLUMN+',' LIST2
FROM Tb1
)DT
LEFT OUTER JOIN TB N ON (N.NUMBER < LEN(DT.LIST2)) OR (N.NUMBER=1 AND DT.LIST2 IS NULL)
WHERE SUBSTRING(LIST2, NUMBER, 1) = ',' OR LIST2 IS NULL
) DT2
WHERE S_DATA<>''
and also you should create a table 'NUMBER' before running the above query.
CREATE TABLE TB (Number INT)
DECLARE #I INT=0
WHILE #I<1000
BEGIN
INSERT INTO TB VALUES (#I)
SET #I=#I+1
END

How do I pivot with hour format(HH:HourNumber)?

I have OrderInfo table which contains OrderTime(date+time),OrderTrackDate(date),OrderTotal(sales amount) columns as shown in the following image.
1. Table1(Original Table)
Here is the code I have tried so far before pivoting.
SELECT CAST(DATEPART(DAY, OrderTime) as varchar)+'/'+ CAST(DATEPART(MONTH, OrderTime) as varchar)+'/'+CAST(DATEPART(year,OrderTime) as varchar) as daymonthyear,
ROUND(SUM(OrderTotal),2) AS Sales, COUNT(OrderTotal) AS Orders
,datepart(hour,OrderTime) as HH
FROM OrderInfo where OrderTime >= '5/24/2013' AND OrderTrackDate <='5/30/2013'
GROUP BY DATEPART(year, OrderTime),DATEPART(MONTH, OrderTime),DATEPART(day, OrderTime),datepart(hour,OrderTime)
Order By daymonthyear,HH
2. Table 2(Grouped according to Date,Hour from Table1)
How do I pivot dynamically and show sales amount per hour based on Table2?
DESIRED OUTPUT
First of all create a temp table to use it in 3 places - Select columns for pivot, Replace null with zero and inside pivot.
SELECT DISTINCT
SUM(ORDERTOTAL) OVER(PARTITION BY CAST(ORDERTIME AS DATE),DATEPART(HH,ORDERTIME)) [TOTAL],
CONVERT(varchar, CAST(ORDERTIME AS datetime), 103) [DATE],
DATEPART(HH,ORDERTIME) [HOUR],
'HH:'+CAST(DATEPART(HH,ORDERTIME) AS VARCHAR(3)) [HOURCOL]
INTO #NEWTABLE
FROM ORDERTBL
ORDER BY DATEPART(HH,ORDERTIME)
Now declare 2 variables to select columns for pivot and replace null with zero
DECLARE #cols NVARCHAR (MAX)
DECLARE #NullToZeroCols NVARCHAR (MAX)
SELECT #cols = COALESCE (#cols + ',[' + [HOURCOL] + ']',
'[' + [HOURCOL] + ']')
FROM (SELECT DISTINCT [HOUR],[HOURCOL] FROM #NEWTABLE) PV
ORDER BY [HOUR]
SET #NullToZeroCols = SUBSTRING((SELECT ',ISNULL(['+[HOURCOL]+'],0) AS ['+[HOURCOL]+']'
FROM(SELECT DISTINCT [HOUR],[HOURCOL] FROM #NEWTABLE GROUP BY [HOUR],[HOURCOL])TAB
ORDER BY [HOUR] FOR XML PATH('')),2,8000)
Now pivot the result
DECLARE #query NVARCHAR(MAX)
SET #query = 'SELECT [DATE],' + #NullToZeroCols + ' FROM
(
SELECT [HOURCOL],[TOTAL], [DATE] FROM #NEWTABLE
) x
PIVOT
(
SUM([TOTAL])
FOR [HOURCOL] IN (' + #cols + ')
) p
;'
EXEC SP_EXECUTESQL #query
SQL FIDDLE

SQL average from multiple columns

How do I get the average from multiple columns?
for example:
Columns: ID 125Hz 250Hz 500Hz 750Hz 1000Hz 1500Hz 2000Hz 3000Hz 4000Hz 6000Hz 8000Hz
Values: 1 92 82 63 83 32 43 54 56 54 34 54
I want to get the average of all the columns except the ID. How do I do that?
You have to manually add the columns since there's no available built-in functions for horizontal aggregation.
select (125Hz+250Hz+500Hz+750Hz+1000Hz+1500Hz+2000Hz+3000Hz+4000Hz+6000Hz+8000Hz)/11 as aveHz from table_name
In SQL-SERVER you can use this
DECLARE #total int
DECLARE #query varchar(550)
DECLARE #ALLColumns VARCHAR(500)
SET #ALLColumns = ''
----Build the string columns
SELECT #ALLColumns = #ALLColumns + '+' + '['+sc.NAME+']'
FROM sys.tables st
INNER JOIN sys.columns sc ON st.object_id = sc.object_id
WHERE st.name LIKE '%YOUR_TABLE_NAME%'
AND sc.NAME LIKE '[0-9]%';--[0-9]% just get the column that start with number
----Get the total number of column,
SELECT #total = count(*) FROM sys.tables st
INNER JOIN sys.columns sc ON st.object_id = sc.object_id
WHERE st.name LIKE '%YOUR_TABLE_NAME%'
AND sc.NAME LIKE '[0-9]%';--[0-9]% just get the column that start with number
SET #query = 'SELECT SUM('+ SUBSTRING(#ALLColumns,2,LEN(#ALLColumns))+')/'
+CAST(#total as varchar(4))+ ' AS [AVG]
FROM [YOUR_TABLE_NAME]
GROUP BY [ID]'
--SELECT #query
EXECUTE(#query)
This will execute a query like this one:
SELECT SUM([125Hz]+[250Hz]+[500Hz]+[750Hz]+[1000Hz]+[1500Hz]+[2000Hz]
+[3000Hz]+[4000Hz]+[6000Hz]+[8000Hz])/11 AS [AVG]
FROM [YOUR_TABLE_NAME] GROUP BY [ID]
UPDATE
Add a column to store the avg, I called it [AVG] and chage the value of #query to
SET #query = '
CREATE TABLE #Medition (ID int,[AVG] decimal(18,4))
INSERT INTO #Medition (ID,[AVG])
SELECT ID,SUM ('+ SUBSTRING(#ALLColumns,2,LEN(#ALLColumns))+')/'
+CAST(#total as varchar(10))
+ ' AS [AVG] FROM Medition GROUP BY ID
UPDATE YOUR_TABLE_NAME SET YOUR_TABLE_NAME.[AVG] = #Medition.[AVG]
FROM YOUR_TABLE_NAME INNER JOIN #Medition ON YOUR_TABLE_NAME.ID =#Medition.ID
DROP TABLE #Medition
'
Note: Build queries string is a little ugly
Another way to do it, without actually using the magic number 11, be it a little more verbose.
WITH t1 AS
(
SELECT * FROM myTable
WHERE (...) -- Should limit result to 1 row
),
t2 AS
(
SELECT col1 FROM t1
UNION ALL
SELECT col2 FROM t1
UNION ALL
(...)
)
SELECT AVG(col1) FROM t2;
this will display Average value of all that fields of each ID you have.
SELECT AVG(125Hz+250Hz+500Hz+750Hz+1000Hz+1500Hz+2000Hz+3000Hz+4000Hz+6000Hz+8000Hz)
AS Average FROM table
GROUP BY ID
SELECT sum(125Hz + 250Hz + 500Hz + 750Hz + 1000Hz + 1500Hz + 2000Hz + 3000Hz +
4000Hz + 6000Hz + 8000Hz)/11 as averageHz from TABLE

PIVOT with Multiple Dates inside "IN" clause

I have here some problem on inserting multiple dates inside in clause.
Here is the code that I have seen through the internet research.
;with cte (datelist, maxdate) as
(
select min(arrivaldate) datelist, max(departuredate) maxdate
from BookingsPerPerson
union all
select dateadd(dd, 1, datelist), maxdate
from cte
where datelist < maxdate
)
select c.datelist
into #tempDates
from cte c
select *
from
(
select b.person_id, b.arrivaldate, b.departuredate,
d.datelist,
convert(CHAR(10), datelist, 120) PivotDate
from #tempDates d
left join BookingsPerPerson b
on d.datelist between b.arrivaldate and b.departuredate
) x
pivot
(
count(datelist)
for PivotDate in ([2012-01-01], [2012-01-02], [2012-01-03],
[2012-01-04], [2012-01-05], [2012-01-06] , [2012-01-07])
) p;
Since the code is manually adding the dates inside the IN clause
pivot
(
count(datelist)
for PivotDate in ([2012-01-01], [2012-01-02], [2012-01-03],
[2012-01-04], [2012-01-05], [2012-01-06] , [2012-01-07])
) p;
Can I just use the date which is extract/split by this code
;with cte (datelist, maxdate) as
(
select min(arrivaldate) datelist, max(departuredate) maxdate
from BookingsPerPerson
union all
select dateadd(dd, 1, datelist), maxdate
from cte
where datelist < maxdate
)
select c.datelist
into #tempDates
from cte c
And use the SELECT statement on the "IN" clause inside the pivot statement?
like this?
pivot
(
count(datelist)
for PivotDate in (select c.datelist from #tempDates)
) p;
I tried this but it gives me an error?
Is there any way that I can add multiple dates from
a temporary table and include it inside the IN clause?
YOU CAN TRY IT HERE : http://sqlfiddle.com/#!3/8857c/9
Yes there is a way. you place first the concatenated dates in one variable..
for example:
DECLARE #dateArray AS VARCHAR(500)
SELECT #dateArray = '02/01/2014,02/02/2014,02/03/2014,02/04/2014'
then create a dynamic sql query:
set #query = 'SELECT * FROM TABLE
PIVOT (count(datelist) PivotDate in (' + #dateArray + '))
hope it helped you in a way. :)

Would using dynamic SQL + variables speed up my query?

I've realized lately that queries are much slower when I reference a variable in the filter instead of the actual value in SQL Server 2008. For example:
SELECT table_A.fruit
, SUM(table_B.units)
FROM table_A LEFT JOIN table_B
ON table_A.fruit = table_B.fruit_name
WHERE time_of_sale BETWEEN '2012-11-01' AND '2012-11-25'
is faster than
DECLARE #date1 DATE = '2012-11-01'
, #date2 DATE = '2012-11-25'
SELECT table_A.fruit
, SUM(table_B.units)
FROM table_A LEFT JOIN table_B
ON table_A.fruit = table_B.fruit_name
WHERE time_of_sale BETWEEN #date1 AND #date2
Would changing my query to this make the query as fast as the first one I posted:
DECLARE #date1 DATE = '2012-11-01'
, #date2 DATE = '2012-11-25'
DECLARE #exec VARCHAR(8000)
SELECT #exec =
'
SELECT table_A.fruit
, SUM(table_B.units)
FROM table_A LEFT JOIN table_B
ON table_A.fruit = table_B.fruit_name
WHERE time_of_sale BETWEEN ''' + #date1 + ''' AND ''' + #date2 + '''
'
EXEC(#exec)