Insert by date using Openquery using SQL Server Linkedserver? - sql-server

I use the below Openquery statement to connect to the linked server and then I want to fetch those records to my local server. The problem is that I want to change the date every day in the where statement below, so I want to make an Openquery by putting the system date as a variable, but an error occurs. Please help me.
INSERT INTO [A-SERVER\SQLEXPRESS].[ASQL].[dbo].[ATB]
SELECT * FROM OPENQUERY ([LINKB], 'SELECT T.DATE, T.ID, O.DES,S.PR,SUM(T.TQ), P.T1, P.T2,
P.T3, P.T4, SUM(T.TL)
FROM [BSQL].[dbo].[BDL] T
JOIN [BSQL].[dbo].[OBT] O ON O.ID = T.ID
JOIN [BSQL].[dbo].[POT] P ON P.ID = T.ID
JOIN [BSQL].[dbo].[ICE] S ON S.ID = T.ID
WHERE CAST(T.DATE AS DATE) = ''2022-07-28'' AND T.TOL = ''3''
GROUP BY T.DATE, T.ID, O.DES, S.PR, P.T1, P.T2,P.T3, P.T4 ');
GO

use GETDATE() cast it as Date
Returns the current a DateTime value of the database system
select CAST(GETDATE() AS DATE); --2022-07-29
So in your condition change the static date ''2022-07-28'' with GETDATE() to get the date dynamically:
WHERE CAST(T.DATE AS DATE) = CAST(GETDATE() AS DATE)

Related

Loops on SQL Server

I have the following query where I input a date and it give me the result. However, I need to run this for 60 different dates. Instead of running this 1 by 1, is there anyway to automate this so it runs each time on a different date?
IF OBJECT_ID('tempdb..#1') IS NOT NULL DROP TABLE #1
declare #d1 datetime = '2020-02-06'
select distinct [User] into #1
from [X].[dbo].[Table1]
where [status] = 'Success'
and [Date] = #d1;
select count(distinct [User])
from #1
inner join [Y].[dbo].[Table2]
on #1.[User] = [Y].[dbo].[Table2].User
where [Date2] between #d1 and #d1+1
and [Checkname] in ('Check1','Check2')
Loops are slow and generally a bad practice in the context of T-SQL. You can use something like this to get the count of users for a batch of dates:
DROP TABLE IF EXISTS #DataSource;
CREATE TABLE #DataSource
(
[Date] DATETIME
,[UsersCount] INT
);
INSERT INTO #DataSource ([Date])
VALUES ('2020-02-06')
,('2020-02-07')
,('2020-02-08');
IF OBJECT_ID('tempdb..#1') IS NOT NULL DROP TABLE #1
select distinct DS1.[Date]
,DS1.[User]
into #1
from [X].[dbo].[Table1] DS1
INNER JOIN #DataSource DS2
ON DS1.[Date] = DS2.[Date]
where DS1.[status] = 'Success';
select #1.[date]
,count(distinct [User])
from #1
inner join [Y].[dbo].[Table2]
on #1.[User] = [Y].[dbo].[Table2].User
where [Date2] between #1.[date] and #1.[date] + 1
and [Checkname] in ('Check1','Check2')
GROUP BY #1.[date]
First, I want to say that gotqn's answer is a good answer - however, I think there are a few more things in the original code that can be improved - so here is how I would probably do it:
Assuming the dates are consecutive, use a common table expression to calculate the dates using dateadd and row_number.
Then, use another common table expression to get the list of dates and users from table1,
and then select the date and count of distinct users for each date from that common table expression joined to table2:
DECLARE #StartDate Date = '2020-02-06';
WITH Dates AS
(
SELECT TOP (60) DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY ##SPID) -1, #StartDate) As Date
FROM sys.objects
), CTE AS
(
SELECT t1.[User], t1.[Date]
FROM [X].[dbo].[Table1] AS t1
JOIN Dates
ON t1.[Date] = Dates.[Date]
WHERE [status] = 'Success'
)
SELECT cte.[Date], COUNT(DISTINCT [User])
FROM CTE
JOIN [Y].[dbo].[Table2] As t1
ON CTE.[User] = t1.[User]
AND t1.[Date2] >= CTE.[Date]
AND t1.[Date2] < DATEADD(Day, 1, CTE.[Date])
AND [Checkname] IN ('Check1','Check2')
GROUP BY cte.[Date]
If the dates are not consecutive, you can use a table variable to hold the dates instead of calculating them using a common table expression.

DB query for x day that no data

I have table contain multiple records for the name and DT, I need a query to check the Name don't have any new record in past 2 days based on the DT, how to create
Name DT
ABC 2017-09-17 06:02:23.000
ACD 2017-09-15 06:02:23.000
I think You need something like this:
SELECT Name,dt
from
(SELECT Name,MAX(dt) dt
FROM your_table
GROUP BY NAME) a
where dt < GETDATE()-2
Without knowing your table schema or sample data this is a wild guess at a query, but what you want should be doable with the GETDATE() function. If you want to use UTC time you can also use the GETUTCDATE() function.
Edit: Updated to include the ROW_NUMBER() function.
Edit 2: Replaced the GETDATE() where clause with a CTE to exclude names that have dt within the last 2 days.
WITH CTE AS (
SELECT
name
FROM table
WHERE dt > GETDATE()-2
)
SELECT
name,
dt
FROM (
SELECT
name,
dt,
ROW_NUMBER() OVER (PARTITION BY name ORDER BY dt desc) AS rn
FROM table
LEFT JOIN CTE ON
table.name = CTE.name
WHERE CTE.name IS NULL
) tbl
WHERE rn = 1
BEGIN TRAN
CREATE TABLE #CM (Name NVARCHAR(06), DT DATETIME)
INSERT INTO #CM
SELECT 'ABC','2017-09-17 06:02:23.000' UNION ALL
SELECT 'ACD','2017-09-15 06:02:23.000'
SELECT * FROM #CM
WHERE CONVERT(NVARCHAR(105),dt) < CONVERT(NVARCHAR(105),GETDATE()-2)
ROLLBACK TRAN

Using BETWEEN operator in CASE (THEN) statement

I am trying the following but its throwing an error, can someone tell me what I am doing wrong?
SELECT custType, count(*)
FROM tbl1 a
LEFT JOIN tbl2 b ON a.tbID = b.tbID
AND ((CustType IN ('Apple','IPAD') and date BETWEEN #StartDate AND #EndDate)
or (CustType IN ('Samsung','LCD') and date BETWEEN #StartDateLL AND #EndDateLL))
GROUP BY CustType
Why don't use AND/OR
SELECT CustType , count(*)
FROM tbl1 a
LEFT JOIN tbl2 b ON a.tbID = b.tbID
AND ((CustType IN ('Apple','IPAD') and date BETWEEN #StartDate AND #EndDate)
or (CustType IN ('Samsung','LCD') and date BETWEEN #StartDateLL AND #EndDateLL))
group by CustType ;
EDIT You can't group by CustType and Select *
You cannot use a BETWEEN operator for the THEN part of a case statement or IIF. BETWEEN is the condition that translates to true and false. So it is VALUE BETWEEN A AND B and would be apart of the WHEN section of a case statement.
Also the case statement returns a value not a formula to be further executed.
I agree with #Vercelli's solution but to show you how a case statement works in the method you are trying you could do the following:
SELECT *
FROM tbl1 a
LEFT JOIN tbl2 b ON a.tbID = b.tbID
AND (CASE
WHEN CustType IN ('Apple','IPAD') AND [date] ETWEEN #StartDate AND #EndDate THEN 1
WHEN CustType IN ('Samsung','LCD') AND [date] BETWEEN #StartDateLL AND #EndDateLL THEN 1
ELSE 0 END) = 1
Again go with #vercelli's answer as it is the more appropriate way of writing the SQL query.

Not able to fetch records by Date from database

I have data based on column id and date...Data Type for date is DATETIME
DataBase : sql server 2008
Query 1:
Select *
from table t1
where (t1.date between '2016-05-11' and '2016-05-13')
Query 2:
select *
from table t1
where t1.date IN ('2016-05-11')
Result is NUll even i have records on this date
So is there any Alternative to fetch records except (<=/</>/>=) greater than or less than
You can use below query but your query is also correct and its running on my server.
Select * from table t1
where t1.date between '20160511 00:00:00' and '20160513 23:59:59';
select * from table t1 where cast(t1.date as date) IN ('20160511');
Try this,
Select *
from table t1
where cast(t1.date as date) between '2016-05-11' and '2016-05-13'
ie Convert your datetime column to date and compare, because your parameters are only date values.
or
where cast(t1.date as date) in ('2016-05-11')--For your second query
or use greater than or less than
Select *
from table t1
where t1.date >= '2016-05-11' and t1.date < '2016-05-14'

Select and count statement

I am new and learning SQL on Microsoft SQL Server 2008. I am trying to do the following for a table of order line items each record is one order item.
any transaction numbers with only one record and a code of #####.
I have tried many ways but haven't been able to figure it out
Select * from Table
where count(transactionnumber)<2 and Code='9987'
I think I got it. Had to use a different code because QA didn't have an distinct rows with that code. Let me know if you see anything that might cause and issue.
Select * from (select Orders.TransactionNumber from Orders
group by Orders.TransactionNumber
having COUNT (Orders.TransactionNumber)=1) as transa
Inner join Orders on transa.TransactionNumber=Orders.TransactionNumber
where ItemCode=9803
Ended up with this code
use XXX
Select Orders.TransactionNumber,Orders.RepNumber, Orders.CustomerID,Orders.ShipToId,orders.ItemCode,Orders.Quantity,Orders.ReceivedDate,Orders.TransmitStatus from (select TransactionNumber from Orders
group by TransactionNumber
having COUNT (TransactionNumber)=1) as transa
Inner join Orders on Orders.TransactionNumber=transa.TransactionNumber
where ItemCode=9987 and ReceivedDate > DateADD (day, -1, GetDate() )
IF ##ROWCOUNT > 0
BEGIN
EXEC msdb.dbo.sp_send_dbmail
recipients=N'XXXX',
#body='Merchandisers orders with only Item Code 9803',
#subject ='only Item Code 9803',
#profile_name ='',
#query = 'Select Orders.TransactionNumber,Orders.RepNumber,Orders.CustomerID,Orders.ShipToId,orders.ItemCode,Orders.Quantity,Orders.ReceivedDate,Orders.TransmitStatus from(select TransactionNumber from Orders
group by TransactionNumber
having COUNT (TransactionNumber)<2) as transa
Inner join Orders on Orders.TransactionNumber=transa.TransactionNumber
where ItemCode=9803 and ReceivedDate > DateADD (day, -1, GetDate() )'
END'
Your query should include something to group by (Name, TransactionNumber, etc.) do a count and constrain on that.
SELECT TransactionCode, COUNT(*)
FROM TABLE
GROUP BY TransactionCode
HAVING COUNT(*) < 2
AND ItemCode = 9987
You may consider using the OVER keyword, so that you don't need to muck around the count(*) and group by so much. That way you can see counts without grouping.
Select *, count(*) over (partition by transactioncode) as "TheCounts"
from table
--where itemcode = 9903
or
Select *, count(*) over (partition by transactioncode, itemcode) as "TheCounts"
from table
--where itemcode = 9903
Here is what I ended up with on this that seems to be working correctly for about a week now it executes a sp_send_dbmail only if there are records.
Select Orders.TransactionNumber, Orders.RepNumber, Orders.CustomerID,Orders.ShipToId,orders.ItemCode,Orders.Quantity,Orders.ReceivedDate,Orders.TransmitStatus from (select TransactionNumber from Orders
group by TransactionNumber
having COUNT (TransactionNumber)=1) as transa
Inner join Device_Orders on Orders.TransactionNumber=transa.TransactionNumber
where ItemCode=9987 and ReceivedDate > DateADD (day, -1, GetDate() )
IF ##ROWCOUNT > 0

Resources