find column which have biggest number of approved transactions sql server - sql

I need to find the Filiyal which have biggest number of approved transactions.
I've try like this:
select max(Filiyal)
from Transactions
where Status = 'Approved'
But it gives me wrong result. Where I'm wrong?
Here is my table:
Filiyal | Status
-------------------------
Bank1 | Approved
Bank2 | Not Approved
Bank1 | Approved
Bank4 | Approved

Your query as written would give you the largest value of Filiyal (alphabetically) from the set of banks that have an approved status. If what you are looking to find is the Filiyal with the most approved records, then you need to have something that counts the records that are approved.
select top 1 Filiyal
from Transactions
where Status = 'Approved'
group by Filiyal
order by COUNT(Filiyal) desc
The group by clause returns a record for each Filiyal and the order by orders them by the number of records for each value that has 'Approved' as a status. The "top 1" will return only the record with the most approved records. In case of a tie though you will get one of them randomly.

You can try with order by desc and top 1:
select top 1 Filiyal
, count(*) as total_approved
from Transactions
where status = 'Approved'
group by Filiyal
order by total_approved desc
P.S. Doesn't cover cases when multiple Filiyals can have the same amount of maximum total_approved.

Related

SQL: Get count of rows for values in another column even when those values do not exist

I have a table named 'products' with two columns: name and status.
I would like to get the count of rows in the table with statuses as Draft, Published and Rejected.
This is the query I tried,
select count(*), status from products where status in ('Draft', 'Published') group by status;
At the moment the table does not have any row with the status as Published or Rejected.
So the above query just returns one row with status and Draft along with its count
count | status
-------+--------
24 | Draft
However, I would like to the query result with the other statuses as zero.
count | status
-------+--------
24 | Draft
0 | Published
0 | Rejected
How should I write the query so that I get the results as above?
You need a list of the statuses and a left join:
select v.status, count(p.status)
from (values ('Draft'), ('Published'), ('Rejected')
) v(status) left join
products p
on p.status = v.status
group by v.status;

SQL SELECT one row per invoice number where there are no success status

I have a table with financial transactions records. It has invoice_number and status columns. There can be more then one row per invoice_number, meaning that there can be unsuccessful transactions.
I need to query last declined transaction if there is no successful one for certain invoice.
invoice_number | status
1 | declined
1 | successful
2 | declined
2 | declined
In the example above I need to get only the last row.
How SQL query could look like.
Thank you.
You need a way to get the last transaction. Here is one approach:
select distinct on (invoice_number) t.*
from transactions t
where not exists (select 1
from transactions t2
where t2.invoice_number = t.invoice_number and
t2.status = 'successful'
)
order by invoice_number, created_at desc;
If you just want the date, you can use aggregation:
select t.invoice_number, max(t.created_at)
from transactions t
group by t.invoice_number
having sum( (t.status = 'successful')::int ) = 0;

sql query in a performant way

In my case there is a table called ServiceCarrier as below:
ServiceId CarrierId
1 1
2 1
4 1
1 2
2 2
5 2
1 20028
2 20028
5 20028
I want to group it by CarrierId and want to get the intersection in between grouped ones.
my expected result is as below
ServiceId
1
2
Assuming (serviceid, carrierid) is unique. GROUP BY serviceid and get the count(*). This will tell how many carriers do offer the service. Since you want only services offered by all carriers, limit the result in a HAVING clause to only keep the services, which have a count equal to the count of all carriers. That indicates the service is offered by all carriers.
SELECT serviceid
FROM elbat
GROUP BY serviceid
HAVING count(*) = (SELECT count(DISTINCT carrierid)
FROM elbat);
SQL Fiddle
To get what you wrote as 'expected' and 'intersection', perhaps try this?
select serviceID from TSO where serviceID=carrierID
If you would like an aggregation, for example, count or sum, perhaps try this?
select serviceID, count(carrierID) as count from TSO where
serviceID=carrierID group by serviceID

Top n records per group sql in access

I am making some software that tracks the scores of a test. There are multiple users, the details of which are stored in a user table. There is then a progress table which tracks a score with the date and the user who's score it is.
I can already select the 3 most recent records for a chosen userID
SELECT TOP 3 Progress.LoginID, Progress.Score, Progress.[Date Taken]
FROM Progress
WHERE (((Progress.LoginID)=[Enter LoginID:]))
ORDER BY Progress.[Date Taken] DESC;
And I can show all the records grouped by LoginID
SELECT Progress.LoginID, Progress.Score, Progress.[Date Taken]
FROM Progress
GROUP BY Progress.LoginID, Progress.Score, Progress.[Date Taken];
I want to be able to show the 3 most recent records for each user in one query and I'm unsure of how to use nested queries/subqueries to do so.
The field names for the user table are:
LoginID
Forename
Surname
DOB
Guardian Forename
Guardian Surname
Telephone Number
The field names for the progress table are:
ProgressID
LoginID
Score
Date Taken
Any help would be appreciated.
I had a similar problem a year ago: Top 3 per group including 0
Using the same approach, this will return the latest three dates for each LoginID - you may get more than three records if there are tied dates for the same LoginID.
SELECT PR1.LogInID, PR1.Score, PR1.[Date Taken]
FROM Progress AS PR1
WHERE PR1.[Date Taken] IN (
SELECT TOP 3 PR2.[Date Taken]
FROM Progress PR2
WHERE PR2.LoginID = PR1.LoginID
ORDER BY PR2.[Date Taken] DESC
)
ORDER BY LoginID, [Date Taken]
You can put your statement without top ranking into brackets and do your ranking in a second step simple as that:
SELECT Top 3 step1.*
FROM (<YOUR STATEMENT>) AS step1
The question is older but it might be a solution though.

How to select data based on two tables

I have two tables and want to select only the ones where a certain status is 'complete' in the second table. The most important factor is that all shipments need to be completed.
First Table (orders) includes a unique order id and several cells with customer details. For example
Order_id | Name
1001 | John
1002 | Paula
1003 | Ben
The second table (shipments) has all the items a customer ordered and the status whether they were delivered e.g.
Order_id | Shipment_number | Status
1001 | 8004 | complete
1001 | 8003 | processing
1002 | 8005 | complete
1003 | 8008 | processing
1003 | 8007 | processing
1003 | 8009 | complete
I tried it with the following code but unfortunately the results show all order ids where at least one of the associated shipments is 'complete'.
SELECT
order_id,
name
FROM orders
INNER JOIN shipments ON orders.order_id = shipments.order_id
WHERE
shipments.status = 'complete';
I'm pretty new to SQL and really struggling with this. Thanks in advance :)
SELECT Orders.OrderID
FROM orders
WHERE NOT EXISTS (SELECT OrderID
FROM shipments
WHERE status != 'complete' AND
shipments.OrderID = Orders.OrderID)
You can use nested queries to do this:
Write a query to take a count of the shipments.order_id group by order_id, this gives you the total shipments for each order, select the order_id and the count.
Write a query to take a count of the shipments.order_id group by order_id where shipments.status = 'complete', this gives you the completed shipments for each order, select the order_id and the count.
join the result of 1 and 2 with order on order id where (1.count = 2.count), select the name and the order_id.
You could try this
SELECT order_id FROM <orders>
WHERE order_id NOT IN (SELECT order_id FROM <shipments> WHERE status <> 'complete')
Even though, depending on your system I would consider adding a field in order table (effectively de-normalizing it, but benefits/drawbacks depend on how often you need this information) and update it with current order status.
If you need this information often, I might be worth it.
SELECT ship.order_id, ord.name
FROM shipments as ship
left join orders as ord on
ord.order_id = ship.order_id
where ship.status = 'complete'
Generally, the best way to do this is to have a level at the order itself that indicates whether or not the order is completely shipped.
But, this would work although it might not scale really well. To get it to scale better, you would have to do another join BACK to orders in the subqueries to limit the orders that you are looking through.
select order_id, name from
orders JOIN
(select order_id, count(*) from shipments where status = 'complete' group by order_id
INTERSECT
select order_id, count(*) from shipments group by order_id)
on order_id