SQL JOIN WITH WHERE - sql-server

I am trying to join a table variable table and another table.
#ProcessTbl OrderDetail
Order ID
Status Order
Approved DateTime
Domain Status
OrderDetail table has multiple columns for same order. For example
ID Order DateTime Status
1 1 11-17-10 Recived
2 1 11-18-10 Processing
3 1 11-19-10 shipped
so what i want the join to do is take the order number from #processtbl(table variable)
and for max(id) get the datetime in this case the max id is 3
so my result should be
order status approved domain datetime
1 shipped true finance 11-19-10
SELECT t.order
,[od.DateTime]
,t.Status
,t.Domain
,t.Approved
FROM #ProcessTable t
JOIN OrderDetail od ON od.order= t.order
WHERE od.ID = (SELECT MAX(id) FROM orderdetail WHERE od.order = t.order )
ORDER BY od.[DateTime], Approved ASC
But I am still getting duplicate records , looks like it is joning both the tables.
How can I get distinct records?

select p.order, od.status, p.approved, p.domain, od.datetime
from #ProcessTable p
inner join (
select Order, max(ID) as MaxID
from OrderDetail
group by Order
) odm
inner join OrderDetail od on odm.Order = od.Order
and odm.MaxID = od.ID

Just a thought, have you tried to perform a SELECT DISTINCT?

WHERE od.ID = (SELECT MAX(id) FROM orderdetail WHERE od.order = t.order )
The od.order is not referencing the orderdetail table in the sub query but the instance outside.
Try something like: WHERE od.ID = (SELECT MAX(id) FROM orderdetail as od1 WHERE od1.order = t.order )

Related

Joining on unique ID and date range - must return 1 row

In my calculated data layer, I am attempting to populate a Customer's postcode at the time of the order, a sub sample of the table being populated is as follows:
CustomerOrders
(
CustomerID varchar(20),
...
OrderDate date,
...
CustomerPostcodeAtTimeOfOrder varchar(10)
)
This table is a join of the Customers table, the Orders table and the CustomerAddress table which looks like follows:
CustomerAddress
(
CustomerID varchar(20),
AddressType varchar(10),
/*
AddressDetails
*/
StartDate date,
EndDate date,
AddressRank int
)
It is quite conceivable that a customer may have recorded addresses of various types for a single date so the intention when populating the CustomerOrders table is to join as below:
SELECT *
FROM Customers c
LEFT JOIN Orders o
ON o.CustomerID = c.CustomerID
OUTER APPLY
(
SELECT TOP 1 Postcode
FROM CustomerAddress ca
WHERE ca.CustomerID = c.CustomerID
AND o.OrderDate BETWEEN ca.StartDate AND ca.EndDate
ORDER BY AddressRank
)
However, the performance hit I am getting by adding this join to the query means that returning 1000 rows goes from taking 4 seconds to taking 106 seconds.
Just to note, I have added a non-clustered index on the Address table too. The definition of which is as below:
CREATE NONCLUSTERED INDEX (IX_CustomerAddress)
ON CustomerAddress (StartDate, EndDate)
INCLUDE (AddressRank, CustomerID, Postcode)
I'm looking for any suggestions on the best way to tackle this issue please?
I'm not completely sure if this will return results faster, but you can rewrite your query like this:
;WITH OrderAddress AS
(
SELECT o.*,
ca.Postcode,
RN = ROW_NUMBER() OVER(PARTITION BY CustomerID ORDER BY AddressRank DESC)
FROM CustomerAddress ca
INNER JOIN Orders o
ON ca.CustomerID = c.CustomerID
AND o.OrderDate BETWEEN ca.StartDate AND ca.EndDate
)
SELECT *
FROM Customers c
LEFT JOIN ( SELECT *
FROM OrderAddress
WHERE RN = 1) o
ON o.CustomerID = c.CustomerID;
You should also post the index definition on the Address table.

create sql query to fetch repeat column values within time frame

Can someone help me with this query? I want to get the result of all the customer_id which repeats more than once in 24hrs
SELECT
O.Order_No, O.Customer_ID, O.DateOrdered, O.IPAddress,
C.FirstName, C.LastName, CD.nameoncard
FROM
Order_No O
INNER JOIN
CardData CD ON O.card_id = CD.id
INNER JOIN
Customers C ON O.customer_id = C.customer_id
ORDER BY
O.order_no desc
adding more details..
so suppose order with customer id xx was placed on 04/23 2:30 pm and again 2nd order was placed with same customer Id xx on same day 04/23 5:30 pm.
i want the query to return me customer Id xx
Thanks
select Customer_ID, CAST(DateOrdered as Date) DateOrdered, count(*) QTDE
from Order_No
group by Customer_ID, CAST(DateOrdered as Date)
having count(*) > 1
To get the customers who have orders issued after the first one, then you could use the following query:
select distinct A.Customer_ID
from Order_No A
inner join (select Customer_ID, min(DateOrdered) DateOrdered from Order_No group by Customer_ID ) B
on A.Customer_ID = B.Customer_ID
and A.DateOrdered - B.DateOrdered <= 1
and A.DateOrdered > B.DateOrdered
SQL Fiddle
To get all customers that have ANY TIME more than one order issued in period less or equal than 24h
select distinct A.Customer_ID
from Order_No A
inner join Order_No B
on A.Customer_ID = B.Customer_ID
and A.DateOrdered > B.DateOrdered
and A.DateOrdered - B.DateOrdered <= 1
SQL Fiddle
Self-join:
SELECT distinct O.Customer_ID
FROM
Order_No O
inner join Order_No o2
on o.customerID = o2.customerID
and datediff(hour, o.DateOrdered, o2.DateOrdered) between 0 and 24
and o.Order_No <> o2.Order_No
This will return all customer_IDs that have ever placed more than one order in any 24 hour period.
Edited to add the join criteria that the matching records should not be the same record. Should return customers who placed two different orders at the same time, but not customers who placed only one order.

Performing a conditional join in SQL Server

I have a SQL Server database. My database has two tables:
Customer Order
-------- -----
ID (int) ID (int)
Name CustomerID (int)
EmailAddress
When I query these tables, I might have a orderID. If I have an order ID, I want to return the customer associated with it. If I do NOT have an order ID, or if it equals 0, I want to return all of the customers. In an attempt to do this, I've written the following query:
SELECT
o.[ID]
FROM
[Order] o
WHERE
o.[ID]=#orderID
This query returns all orders with OrderID. However, I'm not sure how to do my conditional query. Is that even possible in SQL Server? If so, how?
For what you want you could use a case statement with Conduit's answer. Basically
CASE
WHEN #orderid = 0 OR #orderid IS NULL
SELECT * from Customer
ELSE
select c.*
from Customer c
inner join order o
on c.ID = o.CustomerID
where o.orderID = #orderID
END;
It may not be exact, I am not on a box with Sql Server installed.
I can think of a few ways to do this:
SELECT *
FROM Customer
WHERE CustomerID = coalsece( (select TOP 1 customerID from Orders WHERE OrderId= #OrderID), CustomerID)
.
With CustomerOrders As (
SELECT CustomerID, ID as OrderID
FROM Orders
WHERE OrderID = #OrderID
)
SELECT DISTINCT c.*
FROM Customer c
INNER JOIN CustomerOrders co ON c.ID = coalesce(co.CustomerID, c.ID)
You can achieve it using COALESCE in sql server -
SELECT c.*
FROM customer c
WHERE c.Id IN (
SELECT o.[CustomerID]
FROM [Order] o
WHERE o.[ID] = COALESCE(#orderID, o.[ID])
)

Select rows from table1 which don't have rows in table2

I have 2 tables, OrderTable & OrderDetailTable.
I am trying to select rows from OrderTable that don't have any rows in OrderDetailTable so we can Delete them.
I assume you have an id relation between the 2 tables:
select * from OrderTable
where orderdetails_id not in (select id from OrderDetailTable)
and to delete them
delete from OrderTable
where orderdetails_id not in (select id from OrderDetailTable)
SELECT o.*
FROM OrderTable o
LEFT JOIN OrderDetailTable od ON od.idOrderTable = o.id
WHERE od.id IS NULL;
od.id can be any field from OrderDetailTable that can't be null.
Suppose that OrderTable has a column id, and OrderDetailTable has a column orderTable_id
select * from OrderTable
WHERE id not in (
select ot.id from OrderTable ot inner join OrderDetailTable odt on odt.orderTable_id = ot.id
)

Joining table variable and derived table

In the query below #processtable is a table variable and temp is a derived table when I am trying to join them I am getting the following error:
The column prefix 't' does not match with a table name or alias name used in the query.
SELECT t.Order
,CONVERT(NVARCHAR, temp.[DateTime], 101) AS [DateTime]
,t.Status
,t.Domain
,t.Media
,t.Approved
,t.CreatedBy
FROM #ProcessTable t
JOIN (SELECT MAX(Id),Order FROM OrderDetail OD WHERE OD.Order = t.Order) temp
ON temp.Order = t.Order
ORDER BY temp.[DateTime] DESC, Approved ASC
Try this:
SELECT t.Order
,CONVERT(NVARCHAR,temp.[DateTime],101) AS [DateTime]
,t.Status
,t.Domain
,t.Media
,t.Approved
,t.CreatedBy
FROM #ProcessTable t
JOIN (SELECT MAX(Id) AS LatestId, Order FROM OrderDetail OD GROUP BY Order) temp
ON temp.Order = t.Order
ORDER BY temp.[DateTime] DESC, Approved ASC
Note, I've remove the OD.Order = t.Order clause in the nested SELECT and added in a GROUP BY. The condition alongside that join (temp.Order = t.Order) does the filtering so doesn't need to be in the nested select - it was causing the error. Plus as you're using an aggregate function (MAX), you need the GROUP BY.
Also, I've given an alias for MAX(Id) to be returned as
You were almost right...You dont need the where clause in side the derived table if your going to include it as one of the Join criteria.
SELECT
t.Order
,CONVERT(NVARCHAR,temp.[DateTime],101) AS [DateTime]
,t.Status
,t.Domain
,t.Media
,t.Approved
,t.CreatedBy
FROM #ProcessTable t
JOIN (SELECT MAX(Id) AS MaxID,Order, Max([DateTime]) AS [DateTime] FROM OrderDetail OD Group By Order) temp
ON temp.Order = t.Order
ORDER BY temp.[DateTime] DESC, Approved ASC
I don't think you can reference the t.Order in the subquery as such. You should simply rely on the join to handle that clause.
E.g. simply remove the OD.Order = t.Order and allow the join clause to handle it.

Resources