Using MAX in WHERE Clause with < -Operator - sql-server

I want to select the entries in a table when the registration adress is equal to one (of more than one) delivery adresses AND this adress is the adress where the customer sent all his orders to this adress, since the adress was created.
Date 1 = Date of first order to specific adress, Date 2 = Last/Newest Order to specific adress.To make iot easier to understand... I´ve got this (Table1):
The task:
|cID ||company|Street |Code|del |Street2 |Cod2|Date 1 |Date 2 |
+------------------------------------------------------------------------+
|1 ||Ex1 |ABC Rd.1|4025|Ex1 |DEL St.1|0212|01.01.2015|06.03.2015|
|1 ||Ex1 |ABC Rd.1|4025|Ex1 |REF Wy.1|9875|26.02.2015|16.05.2015|
|1 ||Ex1 |ABC Rd.1|4025|Ex1 |ABC Rd.1|4025|13.06.2015|08.08.2015|
|2 ||Ex2 |HIO Wy.1|9999|Ex2 |DEL St.1|0212|13.03.2015|09.07.2015|
|2 ||Ex2 |HIO Wy.1|9999|Ex2 |REG St.1|6754|21.02.2015|16.05.2015|
|2 ||Ex2 |HIO Wy.1|9999|Ex2 |BLA Rd.5|0897|01.03.2015|06.12.2015|
|2 ||Ex2 |HIO Wy.1|9999|Ex2 |HIO Wy.1|9999|09.10.2015|26.11.2015|
|3 ||Ex3 |REG St.1|1114|Ex3 |DEL St.9|0212|13.01.2015|09.02.2015|
|3 ||Ex3 |REG St.1|1114|Ex3 |REG St.1|6754|21.03.2015|16.09.2015|
|3 ||Ex3 |REG St.1|1114|Ex3 |BLA Rd.5|0897|08.06.2015|06.08.2015|
|4 ||Ex4 |FAR RD.9|4567|Ex4 |DDR Wy.2|0897|01.03.2015|06.12.2015|
|4 ||Ex4 |FAR RD.9|4567|Ex4 |FAR RD.9|4567|09.10.2015|26.12.2015|
Expected Result
|cID ||company|Street |Code|del |Street |Code|Date 1 |Date 2 |
+------------------------------------------------------------------------+
|1 ||Ex1 |ABC Rd.1|4025|Ex1 |ABC Rd.1|4025|13.06.2015|08.08.2015|
respectively cID = 1
Here´s what I tried so far, but it´s not working....
SELECT cID
FROM Table1
WHERE company= del
AND Street = Street2
AND Code = Cod2
AND (SELECT MAX (Date 1) > (=! MAX(Date2) FROM Table1 Group by CID)
Edit (To make it more simple to understand):
e.g. the company with the name Ex1 (cID 1) is now located in ABC Rd.1|4025 (actual adress - the adress before is unknown) and has 3 adresses in system, where the orders of the company has been send to.
The first order on adress 1 (DEL St.1|0212) was on 01.01.2015,
the last order to this adress was on 06.03.2015.
The first order on adress 2 (REF Wy.1|9875) was on 26.02.2015
and the last order to this adress was on 16.05.2015 ...
-> I want the cID´s where registration adress (actual adress of the company) is the actual and only delivery adress.

Try using row number to get the latest date.
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER ( PARTITION BY Street, Code, company
ORDER BY Date1 DESC) as rn
FROM Table1
WHERE Street = Street2
AND Code = Cod2
AND company = del
) T
WHERE T.rn = 1

This should work:
SELECT cID
FROM Table1
WHERE Street = Street2
AND Code = Cod2
AND Date1 > (
SELECT MAX(Date2)
FROM Table1 as delivery
WHERE Table1.cID = delivery.cID
AND (delivery.Street2 <> Street OR delivery.Cod2 <> Code)
)
The subquery must itself be a correct SELECT-FROM-WHERE query, and a variable must be used to disambiguate between the outer and inner tables. The inner query selects all deliveries made to the same company but excluding the current delivery, and picks the maximal most recent date. It is then compared to the oldest date of the current delivery address.
Note that the data is not in second normal form. It may be worth, depending on the use case, splitting the table into a table with companies and a table with deliveries.
On my side, it returns 1 as expected.

Related

Skip an entry WHERE ROW_NUMBER() = X And corresponding entry = 'Y'

I have a table with the ROW_NUMBER() partitioned over the User:
Row|Activity|User
-----------------
1 |A |Jeff
2 |A |Jeff
3 |A |Jeff
1 |A |Bob
2 |B |Bob
3 |C |Bob
1 |A |Sam
2 |B |Sam
3 |A |Sam
4 |D |Sam
I would like to skip, during the row count, the entry 3 for Jeff and Sam because if a User's 3rd Activity is A, I should skip it. I call the to-be-skipped rows 'restricted rows'. Basically, I want this table as a result (Without the comments obviously):
Row|Activity|User
-----------------
1 |A |Jeff
2 |A |Jeff --3rd activity is A so it gets skipped
1 |A |Bob
2 |B |Bob
3 |C |Bob --3rd activity isn't A so it doesn't get skipped
1 |A |Sam
2 |B |Sam --3rd activity is A so it gets skipped
3 |D |Sam
My query:
SELECT ROW_NUMBER() OVER(PARTITION BY User) AS Row, Activity, User FROM Table1
WHERE [Filters]
AND User IN(SELECT User IN Table1
WHERE [Filters] --Same filters as above
GROUP BY User HAVING COUNT(User) > 1) --Let's call this the 'Minimum 1 Activity Filter'
I am going to be perfectly honest, right now, I don't know if the Minimum 1 Activity Filter will cause problems later, aka if Row 2 will also have restrictions. Because of that, I prefer treading on the safe side and imagine that I will have to check the Minimum 1 Activity Filter once all the restricted rows have been taken care of.
if a User's 3rd Activity is A, I should skip it
Consider:
select
row_number() over(partition by user order by id) rn,
activity,
user
from (
select
t.*,
row_number() over(partiton by user order id) rn
from mytable t
) t
where not (rn = 3 and activity = 'A')
Note that, for this to work, you do need a column that can be used to sort the records - I assumed column id.

Average calculation between three factors

I need to calculate the average across the past 5 months(APR, MAY, JUN, JUL, AUG). I have 2 splits to consider: Region(6 regions in total) and Status (between Build and Flow-thru). Currently the data is in a weekly format so I rounded up the weeks to get monthly figures. How do i get the average monthly figure using with the two splits. The table looks something like this:
Region|Orders|BuildStatus|Months
GP |1 |Build |APR
GP |2 |Non-Build |APR
GP |1 |Build |MAY
GP |2 |Non-Build |MAY
PD |1 |Build |APR
PD |2 |Non-Build |APR
PD |1 |Build |MAY
PD |2 |Non-Build |MAY
It repeats with 5 other regions up until August.
Please assist with the correct calculation and if possible you can also suggest the query for it.
The Result should be:
Region|Avg_Orders|BuildStatus
GP |1 |Build
GP |2 |Non-Build
PD |1 |Build
PD |2 |Non-Build
The figures on the average should be the average of the 5 months.
Thanks
DECLARE #t TABLE(
Region NVARCHAR(2)
,Orders INT
,BuildStatus NVARCHAR(100)
,Months NVARCHAR(3)
)
INSERT INTO #t VALUES
('GP', 1,'Build', 'APR')
,('GP', 2,'Non-Build', 'APR')
,('GP', 1,'Build', 'MAY')
,('GP', 2,'Non-Build', 'MAY')
,('PD', 1,'Build', 'APR')
,('PD', 2,'Non-Build', 'APR')
,('PD', 1,'Build', 'MAY')
,('PD', 2,'Non-Build', 'MAY');
WITH cteAgg AS(
SELECT t.Region, t.BuildStatus, SUM(t.Orders) Orders, COUNT(DISTINCT t.Months) MonthsCount
FROM #t t
GROUP BY t.Region, t.BuildStatus
)
SELECT Region, Orders/MonthsCount AS Avg_Orders, BuildStatus
FROM cteAgg
ORDER BY 1

Sum up delivered companies for every customer(ID)

I'm back in action ;) This time I have a pretty heavy task (I think).
Here's what I got:
|customerID ||company |compdel |Street |Code |Date 1 |Date 2 |
+-------------------------------+--------------------------------------+
|1 ||Example1 |DELExam1|ABC Rd.1|4025 |01.01.2015 |01.08.2015 |
|1 ||Example1 |DELExam1|ABC Rd.1|4025 |13.04.2015 |01.12.2015 |
|1 ||Example1 |DELExam2|DEL St.1|0212 |13.03.2015 |09.07.2015 |
|1 ||Example1 |DELExam3|REF Wy.1|9875 |26.05.2015 |16.09.2015 |
|2 ||Example2 |DELExam4|REG St.1|6754 |21.02.2015 |16.05.2015 |
|2 ||Example2 |DELExam5|HIO Wy.1|9999 |01.03.2015 |06.08.2015 |
|2 ||Example2 |DELExam5|HIO Wy.1|9999 |01.01.2015 |06.02.2015 |
I want to show for every customerID every delivered company (compdel) summed in one line with the earliest date in Date 1 and the newest Date in Date 2. To make it easier to understand, I want this result:
|customerID ||company |compdel |Street |Code |Date 1 |Date 2 |
+-------------------------------+--------------------------------------+
|1 ||Example1 |DELExam1|ABC Rd.1|4025 |01.01.2015 |01.12.2015 |
|1 ||Example1 |DELExam2|DEL St.1|0212 |13.03.2015 |09.07.2015 |
|1 ||Example1 |DELExam3|REF Wy.1|9875 |26.05.2015 |16.09.2015 |
|2 ||Example2 |DELExam4|REG St.1|6754 |21.02.2015 |16.05.2015 |
|2 ||Example2 |DELExam5|HIO Wy.1|9999 |01.01.2015 |06.08.2015 |
I tried it already with this select-Statement but it won´t work: I know, that this can only be a part of the answer....
SELECT *
FROM
(SELECT
customerID, company, compdel, Street, Code, Date 1, Date 2,
ROW_NUMBER() OVER(PARTITION BY compdel ORDER BY customerID) rn
FROM
table 1) as Y
WHERE
rn = 1
Use GROUP BY with distinct values (customerId, company etc.) and MIN and MAX for dates
SELECT CustomerId
, Company
, CompDel
, Street
, Code
, MIN(Date1) As EarliestDate1
, MAX(Date2) AS NewestDate2
FROM YourTable
GROUP BY CustomerId, Company, CompDel, Street, Code

How to get the count of each distinct value in Multiple columns and get the result in separate columns?

I need the following table to be queried to get the result given below the table.
Table:
----------------------------------
| Name | Age | slot |
|-------|--------|---------------|
|A |20 | 1 |
|B |30 | 2 |
|C |30 | 1 |
|D |20 | 1 |
|E |40 | 2 |
|F |40 | 3 |
|G |50 | 3 |
----------------------------------
Result:
-------------------------------------------
|Age |Age_Count |Slot |Slot_Count|
-------------------------------------------
|20 | 2 |1 |3 |
-------------------------------------------
|30 | 2 |2 |2 |
-------------------------------------------
|40 | 2 |3 |2 |
-------------------------------------------
|50 | 1 |
-----------------------
While searching stackoverflow i found this question for single column question and there is [this link for multiple columns] (get the count of each distinct value in "Multiple" columns) question. The answers from the second link (for the multiple coulmn's distinct count) is displayed under a single column and my requirement is i guess quite different from the answers posted there.
Thanks in advance
Your request is kind of odd. Are you sure you want that?
If so, this may help:
SET #x:=0,#y:=0,#m:=0,#n:=0;
SELECT
DISTINCT age,age_count, slot,slot_count
FROM (
SELECT
age, age_count, slot, slot_count
FROM (
SELECT
#x:=#x + 1 AS aid, age, COUNT(*) age_count
FROM
slots
GROUP BY age
) a
LEFT JOIN (
SELECT
#y:=#y + 1 AS sid, slot, COUNT(*) slot_count
FROM
slots
GROUP BY slot
) s ON a.aid = s.sid
UNION
SELECT
age, age_count, slot, slot_count
FROM (
SELECT
#m:=#m + 1 AS aid, slot, COUNT(*) slot_count
FROM
slots
GROUP BY slot
) a
LEFT JOIN (
SELECT
#n:=#n + 1 AS sid, age, COUNT(*) age_count
FROM
slots
GROUP BY age
) s ON a.aid = s.sid
) a
If you know for sure that you have more unique ages than unique slots , or opposite, you can get ride of messy union.

How can i get all childs row with entity commands?

i used this SQL Command to get all child and childs of child users and i dont know how can i write it with entities?
WITH ParentUser AS (
SELECT *, 1 AS nthLevel
FROM [OnlinePage].[dbo].[Users] usr1
WHERE ID = #UserID
UNION ALL
SELECT usr2.*,
nthLevel + 1 AS nthLevel
FROM ParentUser pu INNER JOIN
[OnlinePage].[dbo].[Users] usr2 ON pu.ID = usr2.UserParentID
)
SELECT * FROM ParentUser WHERE 1 < nthLevel
and my users table is:
CREATE TABLE [dbo].[Users](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Username] [nvarchar](50) NOT NULL,
[UserParentID] [int] NOT NULL
)
it`s something like this:
|--------------------------------------|
|ID |Username |UserParentID |
|-----|-----------|--------------------|
|1 |admin |0 |
|2 |reseler1 |1 |
|3 |user1 |1 |
|4 |reseler2 |2 |
|5 |user2 |4 |
|6 |user3 |5 |
|--------------------------------------|
and if i want to get all childs of reseler1 with upper sql command i change #UserID with 2 and my result is:
|--------------------------------------|
|ID |Username |UserParentID |
|-----|-----------|--------------------|
|2 |reseler1 |1 |
|3 |user1 |1 |
|4 |reseler2 |2 |
|5 |user2 |4 |
|6 |user3 |5 |
|--------------------------------------|
now i need entity model of this sql command,
i search it on google and i found something in stackoverflow(Querying child entities) like down code, but not work correctly and only get one level of childs:
var query = from m in dbSet.Where(x => x.ID == 1)
join s in dbSet
on m.ID equals s.UserParentID into masterSlaves
from ms in masterSlaves.DefaultIfEmpty()
select ms;
Entity framework and Linq-to-entities does not support hierarchical queries. You must use your SQL query and call it with dbSet.SqlQuery or dbContext.Database.SqlQuery. With EF 5 / .NET 4.5 and database first approach you would also be able to create SQL function wrapping your query and map it (so you would be able to use that function from Linq-to-entities query) but that is not available in earlier versions and in code first.

Resources