SQL Server column max based on another column - sql

I have a dataset as shown below in a booking table
Custid ApptDate oldornewApp
-------------------------------
100 01-jan-2013 old
100 01-jan-2014 old
100 01-oct-2016 new
100 12-oct-2016 new
200 01-feb-2015 old
200 10-oct-2016 new
I am trying for an output which shows max date based on the oldornewapp column for each customer
custid MaxApptDateOldApp MaxapptDatenewapp
---------------------------------------------
100 01-jan-2014 12-oct-2016
200 01-feb-2015 10-oct-2016
Please let me know a best way to get the resultset, I am using SQL Server 2012
Thanks in advance

SELECT
Custid
,MAX(CASE WHEN oldornewApp = 'old' THEN ApptDate END) as MaxApptDateOldApp
,MAX(CASE WHEN oldornewApp = 'new' THEN ApptDate END) as MaxApptDateNewApp
FROM
TableName
GROUP BY
Custid
You can use conditional aggregation to get to your desired result.

You can use join and group by
select old.Custid, max(old.ApptDate) as MaxApptDateOldApp, max(new.ApptDate) as MaxApptDateNewApp
from my_table as old
where a.oldornewApp = 'old';
group by a,Custid
inner join (
select b.Custid, max(b.ApptDate) as AppDate
from my_table as b
where b.oldornewApp = 'new';
group by b.Custid
) new

Related

Last record per transaction

I am trying to select the last record per sales order.
My query is simple in SQL Server management.
SELECT *
FROM DOCSTATUS
The problem is that this database has tens of thousands of records, as it tracks all SO steps.
ID SO SL Status Reason Attach Name Name Systemdate
22 951581 3 Processed Customer NULL NULL BW 2016-12-05 13:33:27.857
23 951581 3 Submitted Customer NULL NULL BW 2016-17-05 13:33:27.997
24 947318 1 Hold Customer NULL NULL bw 2016-12-05 13:54:27.173
25 947318 1 Invoices Submit Customer NULL NULL bw 2016-13-05 13:54:27.300
26 947318 1 Ship Customer NULL NULL bw 2016-14-05 13:54:27.440
I would to see the most recent record per the SO
ID SO SL Status Reason Attach Name Name Systemdate
23 951581 4 Submitted Customer NULL NULL BW 2016-17-05 13:33:27.997
26 947318 1 Ship Customer NULL NULL bw 2016-14-05 13:54:27.440
Well I'm not sure how that table has two Name columns, but one easy way to do this is with ROW_NUMBER():
;WITH cte AS
(
SELECT *,
rn = ROW_NUMBER() OVER (PARTITION BY SO ORDER BY Systemdate DESC)
FROM dbo.DOCSTATUS
)
SELECT ID, SO, SL, Status, Reason, ..., Systemdate
FROM cte WHERE rn = 1;
Also please always reference the schema, even if today everything is under dbo.
I think you can keep it this simple:
SELECT *
FROM DOCSTATUS
WHERE ID IN (SELECT MAX(ID)
FROM DOCSTATUS
GROUP BY SO)
You want only the maximum ID from each SO.
An efficient method with the right index is a correlated subquery:
select t.*
from t
where t.systemdate = (select max(t2.systemdate) from t t2 where t2.so = t.so);
The index is on (so, systemdate).

id where column has two conditions

I have a table of customers that join and leave a company
ID ActiveFrom ActiveTo
I have for example a where clause that has
where ActiveFrom <= '20170101'
and Activeto < '20170201'
but some times a customer has decided to re-join the company a few days later because of a deal.
example customer:
ID ActiveFrom ActiveTo
1 2000-01-01 2017-01-03
1 2017-01-28 Null
2 2000-01-01 2017-01-06
I want to exclude the customers that do this, from the customers that leave the company but come back
so I want id 2 to be returned only
please help
You can try this.
SELECT * FROM Customer C1
WHERE C1.ActiveFrom <= '20170101'
AND C1.Activeto < '20170201'
AND NOT EXISTS ( SELECT * FROM Customer C2
WHERE C1.ID = C2.ID
AND C2.ActiveTo IS NULL )
You could use a subquery on WHERE statement:
SELECT *
FROM tablename
WHERE (SELECT id FROM tablename WHERE activeTo is null) <> id
GROUP By id
You can find more information here:
https://www.techonthenet.com/sql_server/subqueries.php

SQL aggregate rows with same id , specific value in secondary column

I'm looking to filter out rows in the database (PostgreSQL) if one of the values in the status column occurs. The idea is to sum the amount column if the unique reference only has a status equals to 1. The query should not SELECT the reference at all if it has also a status of 2 or any other status for that matter. status refers to the state of the transaction.
Current data table:
reference | amount | status
1 100 1
2 120 1
2 -120 2
3 200 1
3 -200 2
4 450 1
Result:
amount | status
550 1
I've simplified the data example but I think it gives a good idea of what I'm looking for.
I'm unsuccessful in selecting only references that only have status 1.
I've tried sub-queries, using the HAVING clause and other methods without success.
Thanks
Here's a way using not exists to sum all rows where the status is 1 and other rows with the same reference and a non 1 status do not exist.
select sum(amount) from mytable t1
where status = 1
and not exists (
select 1 from mytable t2
where t2.reference = t1.reference
and t2.status <> 1
)
SELECT SUM(amount)
FROM table
WHERE reference NOT IN (
SELECT reference
FROM table
WHERE status<>1
)
The subquery SELECTs all references that must be excluded, then the main query sums everything except them
select sum (amount) as amount
from (
select sum(amount) as amount
from t
group by reference
having not bool_or(status <> 1)
) s;
amount
--------
550
You could use windowed functions to count occurences of status different than 1 per each group:
SELECT SUM(amount) AS amount
FROM (SELECT *,COUNT(*) FILTER(WHERE status<>1) OVER(PARTITION BY reference) cnt
FROM tc) AS sub
WHERE cnt = 0;
Rextester Demo

How can I combine 3 queries into one query and the result form look like schedule table?

I have 3 select queries :
the result of first for heading of my table.(like : select id, name from cars)
the second result show left side of my schedule table shows the date of sales (select date from dates inner join car on date.carid = car.carid where date.date1 > XXX/XX/XX for example)
the third result returns the data for inside the table. and it is the price of each car in each date.
But I don't know how to combine them?
I guess you need something like this Working SQL Server fiddle here
You need either of the following
Pivot feature of SQL Server
Aggregate function with group-by
Query: Pivot feature of SQL Server
SELECT *
FROM
(
SELECT [SALE_DATE], [CAR_NAME], [COST]
FROM CARS_SALES
) AS source
PIVOT
(
MAX(COST)
FOR [CAR_NAME] IN ([BENZ] , [BMW], [RENAULT])
) as pvt;
Query: Aggregate function with group-by
SELECT SALE_DATE,
MAX(CASE WHEN CAR_NAME = 'BENZ' THEN COST ELSE NULL END) [BENZ],
MAX(CASE WHEN CAR_NAME = 'BMW' THEN COST ELSE NULL END) [BMW],
MAX(CASE WHEN CAR_NAME = 'RENAULT' THEN COST ELSE NULL END) [RENAULT]
FROM CARS_SALES
GROUP BY SALE_DATE
Both the Queries give an
output result
as below:
SALE_DATE BENZ BMW RENAULT
09/07/2014 (null) (null) 900
09/08/2014 100 200 300
09/09/2014 400 600 (null)
09/10/2014 700 500 800
It's really unclear, but based on that you've posted, the solution would be something like this:
select cars.name, dates.date, dates.price
from dates
left join cars on (cars.carid=dates.carid)
order by cars.name, dates.date;
This gets the car's name, price and the date in one query. But I don't understand what your third query is for. If you provide more information I'll update this answer.

Combine Multiple Sql Queries into one

I have a column called "status" in a sql table called "latest" which contains five different values new,deployed,resolved,assigned and closed as shown below
Status
--------------
NEW
NEW
DEPLOYED
NEW
RESOLVED
ASSIGNED
ASSIGNED
RESOLVED
ASSIGNED
NEW
NEW
RESOLVED
CLOSED
ASSIGNED
I want to write a query in which i can count the number of times each of these words occur in the column "status". Currently I'm using count function in 5 different queries like this.
1)select count(status) from latest where status="NEW";
2)select count(status) from latest where status="DEPLOYED";
3)select count(status) from latest where status="RESOLVED";
4)select count(status) from latest where status="ASSIGNED";
5)select count(status) from latest where status="CLOSED";
Is there a way i could combine all these queries into single query without using joins or union to get 5 different count values??
QUERY 1:
SELECT STATUS, COUNT(1) FROM LATEST
GROUP BY STATUS
ORDER BY STATUS;
Your Output would be:
STATUS COUNT
ASSIGNED 4
CLOSED 1
DEPLOYED 1
NEW 5
RESOLVED 3
To get the output in single row with 5 columns you can use:
QUERY 2:
SELECT COUNT(CASE WHEN STATUS='ASSIGNED' THEN 1 END) ASSIGNED_COUNT,
COUNT(CASE WHEN STATUS='CLOSED' THEN 1 END) CLOSED_COUNT,
COUNT(CASE WHEN STATUS='DEPLOYED' THEN 1 END) DEPLOYED_COUNT,
COUNT(CASE WHEN STATUS='NEW' THEN 1 END) NEW_COUNT,
COUNT(CASE WHEN STATUS='RESOLVED' THEN 1 END) RESOLVED_COUNT
FROM LATEST
Your Output would be:
ASSIGNED_COUNT | CLOSED_COUNT | DEPLOYED_COUNT | NEW_COUNT | RESOLVED_COUNT
4 | 1 | 1 | 5 | 3
EXPLANATION:
Query 1 can be used where there can be any number of dynamic status. For example, even if there is a status named DEFERRED, it would automatically be included without query change. But, if there is say, no record with status as "NEW", then no data would be returned.
Query 2 can be used to return all the data in a single row. If a new status is to be included, then the query must be modified. If there are no records for a status, then 0 would be returned. IDEAL FOR DASHBOARD kind of usage.
Try this cool one
Select *
from
(
Select Status,COUNT(*) 'Count'
from LATEST
group by Status with rollup
) t
where t.Count is not null
Try this:
SELECT l.status, COUNT(1)
FROM latest l
GROUP BY l.status;
OR
SELECT SUM(l.status = 'NEW') AS NEW_STATUS,
SUM(l.status = 'DEPLOYED') AS DEPLOYED_STATUS,
SUM(l.status = 'RESOLVED') AS RESOLVED_STATUS,
SUM(l.status = 'ASSIGNED') AS ASSIGNED_STATUS,
SUM(l.status = 'CLOSED') AS CLOSED_STATUS
FROM latest l;
UPDATE
Use SELECT...INTO statement to achieve this, check below query
SELECT SUM(l.status = 'NEW') AS NEW_STATUS,
SUM(l.status = 'DEPLOYED') AS DEPLOYED_STATUS,
SUM(l.status = 'RESOLVED') AS RESOLVED_STATUS,
SUM(l.status = 'ASSIGNED') AS ASSIGNED_STATUS,
SUM(l.status = 'CLOSED') AS CLOSED_STATUS
INTO NEW_STATUS, DEPLOYED_STATUS, RESOLVED_STATUS,
ASSIGNED_STATUS, CLOSED_STATUS
FROM latest l;
Try This...
1.>
Select Count() as Count,Status from latest where (status='NEW' Or status='DEPLOYED' or status='RESOLVED' or status='ASSIGNED' Or status='CLOSED') group by Status;*
OR
2.>
select count(status) from latest where (status='NEW' Or status='DEPLOYED' or status='RESOLVED' or status='ASSIGNED' Or status='CLOSED');