Multiple counts (over 2000 rows by 2000 columns) - sql

I apologize if I can't explain myself clearly but I'll try my best.
So I need to query a table (money transactions) where in a certain, say branch R1 sends money to another branch (can be any branch (R1 - R2000)). I need to be able to get the count of transactions (money sent). The problem is that there are too many branches (2000+ branches).
The table looks like this:
This is how the results should look like this:
I did the same query with this before but there were only less than 20 branches that were considered. I did something like this.
SELECT
SUM(CASE WHEN BranchCode = 'R1' THEN 1 ELSE 0 END) 'R1',
SUM(CASE WHEN BranchCode = 'R2' THEN 1 ELSE 0 END) 'R2',
.....
SUM(CASE WHEN BranchCode = 'R20' THEN 1 ELSE 0 END) 'R20'
FROM MoneyTable
I want to know if I can be able to do this in a more efficient way.

It's hard to say without more information, such as what your table looks like, but assuming that each for each row, the value in column BranchCode indicates that a particular branch sent money, and you just want to count the number of transactions that the branch sent to any other branch the query would look something like this.
select sending_branch, count(*)
from moneytable
group by 1
Assuming you wanted transaction counts from one branch to another, then something like this.
select sending_branch, receiving_branch, count(*)
from moneytable
group by 1,2
Similarly if you wanted amounts
select sending_branch, receiving_branch, sum(amount)
from moneytable
group by 1,2

Related

How do I count the rows with a where clause in SQL Server?

I am pretty much stuck with a problem I am facing with SQL Server. I want to show in a query the amount of times that specific value occurs. This is pretty easy to do, but I want to take it a step further and I think the best way to explain on what I am trying to achieve is to explain it using images.
I have two tables:
Plant and
Chest
As you can see with the chest the column 'hoeveelheid' tells how full the chest is, 'vol' == 1 and 3/4 is == 0,75. In the plant table there is a column 'Hoeveelheidperkist' which tells how much plants there can be in 1 chest.
select DISTINCT kist.Plantnaam, kist.Plantmaat, count(*) AS 'Amount'
from kist
group by kist.plantnaam, kist.Plantmaat
This query counts all the chests, but it does not seperate the count of 'Vol' chests and '3/4' chests. It only does This. What I want to achieve is this. But I have no idea how. Any help would be much appreciated.
If you use group by you don't need distinct
and if you want the seprated count for hoeveelheid you ust add to the group by clause
select DISTINCT kist.Plantnaam, kist.Plantmaat, kist.hoeveelheid, count(*) AS 'Amount'
from kist
group by kist.plantnaam, kist.Plantmaat, hoeveelheid
or if you want all the 3 count ond the samw rowx you could use a condition aggreagtion eg:
select DISTINCT kist.Plantnaam, kist.Plantmaat
, sum(case when kist.hoeveelheid ='Vol' then 1 else 0 end) vol
, sum(case when kist.hoeveelheid ='3/3' then 1 else 0 end) 3_4
, count(*) AS 'Amount'
from kist
group by kist.plantnaam, kist.Plantmaat
When you want to filter the data on the counts you have to use having clause. When ever you are using aggregate functions(sum, count, min, max) and you want to filter them on aggregation basis, use having clause
select DISTINCT kist.Plantnaam, kist.Plantmaat, count(*) AS 'Amount'
from kist
group by kist.plantnaam, kist.Plantmaat having count(*) = 1 -- or provide necessary conditions

Retrieve the total number of orders made and the number of orders for which payment has been done

Retrieve the total number of orders made and the number of orders for which payment has been done(delivered).
TABLE ORDER
------------------------------------------------------
ORDERID QUOTATIONID STATUS
----------------------------------------------------
Q1001 Q1002 Delivered
O1002 Q1006 Ordered
O1003 Q1003 Delivered
O1004 Q1006 Delivered
O1005 Q1002 Delivered
O1006 Q1008 Delivered
O1007 Q1009 Ordered
O1008 Q1013 Ordered
Unable to get the total number of orderid i.e 8
select count(orderid) as "TOTALORDERSCOUNT",count(Status) as "PAIDORDERSCOUNT"
from orders
where status ='Delivered'
The expected output is
TOTALORDERDSCOUNT PAIDORDERSCOUNT
8 5
I think you want conditional aggregation:
select count(*) as TOTALORDERSCOUNT,
sum(case when status = 'Delivered' then 1 else 0 end) as PAIDORDERSCOUNT
from orders;
Try this-
SELECT COUNT(ORDERID) TOTALORDERDSCOUNT,
SUM(CASE WHEN STATUS = 'Delivered' THEN 1 ELSE 0 END ) PAIDORDERSCOUNT
FROM ORDER
You can also use COUNT in place of SUM as below-
SELECT COUNT(ORDERID) TOTALORDERDSCOUNT,
COUNT(CASE WHEN STATUS = 'Delivered' THEN 1 ELSE NULL END ) PAIDORDERSCOUNT
FROM ORDER
you could use cross join between the two count
select count(orderid) as TOTALORDERSCOUNT, t.PAIDORDERSCOUNT
from orders
cross join (
select count(Status) PAIDORDERSCOUNT
from orders where Status ='Delivered'
) t
What I've used in the past for summarizing totals is
SELECT
count(*) 'Total Orders',
sum( iif( orders.STATUS = 'Delivered', 1, 0 ) ) 'Total Paid Orders'
FROM orders
I personally don't like using CASE WHEN if I don't have to. This logic may look like its a little too much for a simple summation of totals, but it allows for more conditions to be added quite easily and also just involves less typing, at least for what I use this regularly for.
Using the iif( statement to set up the conditional where you're looking for all rows in the STATUS column with the value 'Delivered', with this set up, if the status is 'Delivered', then it marks it stores a value of 1 for that order, and if the status is either 'Ordered' or any other value, including null values or if you ever need a criteria such as 'Pending', it would still give an accurate count.
Then, nesting this within the 'sum' function totals all of the 1's denoted from your matched values. I use this method regularly for report querying when there's a need for many conditions to be narrowed down to a summed value. This also opens up a lot of options in the case you need to join tables in your FROM statement.
Also just out of personal preference and depending on which SQL environment you're using this in, I tend to only use AS statements for renaming when absolutely necessary and instead just denote the column name with a single quoted string. Does the same thing, but that's just personal preference.
As stated before, this may seem like it's doing too much, but for me, good SQL allows for easy change to conditions without having to rewrite an entire query.
EDIT** I forgot to mention using count(*) only works if the orderid's are all unique values. Generally speaking for an orders table, orderid is an expected unique value, but just wanted to add that in as a side note.
SELECT DISTINCT COUNT(ORDERID) AS [TOTALORDERSCOUNT],
COUNT(CASE WHEN STATUS = 'ORDERED' THEN ORDERID ELSE NULL END) AS [PAIDORDERCOUNT]
FROM ORDERS
TotalOrdersCount will count all distinct values in orderID while the case statement on PaidOrderCount will filter out any that do not have the desired Status.

Using Count case

So I've been just re-familiarizing myself with SQL after some time away from it, and I am using Mode Analytics sample Data warehouse, where they have a dataset for SF police calls in 2014.
For reference, it's set up as this:
incident_num, category, descript, day_of_week, date, time, pd_district, Resolution, address, ID
What I am trying to do is figure out the total number of incidents for a category, and a new column of all the people who have been arrested. Ideally looking something like this
Category, Total_Incidents, Arrested
-------------------------------------
Battery 10 4
Murder 200 5
Something like that..
So far I've been trying this out:
SELECT category, COUNT (Resolution) AS Total_Incidents, (
Select COUNT (resolution)
from tutorial.sf_crime_incidents_2014_01
where Resolution like '%ARREST%') AS Arrested
from tutorial.sf_crime_incidents_2014_01
group by 1
order by 2 desc
That returns the total amount of incidents correctly, but for the Arrested, it keeps printing out 9014 Arrest
Any idea what I am doing wrong?
The subquery is not correlated. It just selects the count of all rows. Add a condition, that checks for the category to be equal to that of the outer query.
SELECT o.category,
count(o.resolution) total_incidents,
(SELECT count(i.resolution)
FROM tutorial.sf_crime_incidents_2014_01 i
WHERE i.resolution LIKE '%ARREST%'
AND i.category = o.category) arrested
FROM tutorial.sf_crime_incidents_2014_01 o
GROUP BY 1
You could use this:
SELECT category,
COUNT(Resolution) AS Total_Incidents,
SUM(CASE WHEN Resolution LIKE '%ARREST%' THEN 1 END) AS Arrested
FROM tutorial.sf_crime_incidents_2014_01
GROUP BY category
ORDER BY 2 DESC;

sql select sum off of two where clauses

SELECT Projects.Projectid, Projects.ProjectNumber, Projects.ProjectName,
Projects.ProjectBudgetedIS, Projects.ProjectSpentIS,
Projects.ProjectBudgetedBusiness, Projects.PorjectSpentBusiness, Project.Status,
ProjectStatus.Status AS Expr1
FROM Projects
INNER JOIN ProjectStatus ON Projects.Status = ProjectStatus.StatusID
WHERE Projects.Status = #Status
So what I want to do is take the sum of a table called invoices which has a field called ISorBusiness and a field called totalspent and store that data into the projects tabel in the appropriate field. So that when I get an invoice that is charged to the IS it takes that amount and rolls it into the Projects.ProjectSpentIS and if I get a invoice that is to the business it rolls it into the Projects.ProjectBudgetedBusiness.
I know this should be easy and sorry for the noobish question. Thanks in advance!
I would do something like:
SELECT SUM(CASE WHEN (IsOrBusiness = 'IS') THEN totalSpent ELSE 0 END) AS IsSpent,
SUM(CASE WHEN (IsOrBusiness = 'Business') THEN totalSpent ELSE 0 END) AS BusinessSpent
FROM Invoices
Obviously the usage depends on whether you are trying to write an insert query or select this data as part of the select query you have posted.

MySQL find count query

I have table called stats. In am inserting yes or no in the table, and I want to show the number of yes count and the number of no count.
Can somebody please help me with the query?
select yn, count(*)
from stats
group by yn;
Try something like this
SELECT SUM(CASE WHEN recommend = 'Y' THEN 1 ELSE 0 END) YesCount,
SUM(CASE WHEN recommend = 'N' THEN 1 ELSE 0 END) NoCount,
COUNT(*) TotalCount
FROM Stats
This is exactly what the GROUP BY clause and aggregate functions are for in SQL. The following should be what you need and more efficient then a CASE statement. It returns a table with two columns: recommend and no (which is the count of identical values in the recommend column. If what you said above is true, then this should return at most two rows.
SELECT recommend, count(*) AS no FROM stats GROUP BY recommend