SQL Percentage Count Query By Date - sql

I am able to calculate the percentage count on a particular date in a Microsoft Access 2007 SQL query using:
SELECT Date, Val, (Count(Val) / (SELECT Count(*) From Table HAVING Date=#7/31/2012#) as PercentVal
FROM Table
GROUP BY Date, Val
HAVING Date=#7/31/2012#
However, I would like to make this same calculation over every date using the count totals . For instance, the query:
SELECT Date, Val, Count(*) AS CountVal
FROM Table
GROUP BY Date, Val
finds the counts in every period. I would like to add an additional column with the percent counts. However, I can't seem to figure out how to calculate count percentage in every period without using the above block of text and setting up queries for each individual period.

You can subquery it like this:
SELECT A.ADate, A.Val, COUNT(A.Val) / B.DateCount
FROM Table1 AS A
INNER JOIN (
SELECT C.ADate, COUNT(*) AS DateCount
FROM Table1 C
GROUP BY C.ADate
) AS B ON A.ADate = B.ADate
GROUP BY A.ADate, A.Val, B.DateCount

Related

Select difference between two tables

I want to list four columns, date, hourly count, daily count and difference between two counts.
I have used union all for two tables, but I am getting 2rows as shown in the image:
Select a.date, a.hour,b.daily,sum(a.hour-b.daily)
from (select date,count(*) hour,''daily
From table a union all select '' hour,count(*) daily from table b)
Group by date, daily, hourly..
Please suggest to me a solution.
I see that the code supplied uses a UNION to achieve the output. This would be better served by using a JOIN of some kind.
The result is the total number of rows in table_a grouped by the date subtracted from the total number of rows in table_b grouped by the date.
This code is untested but should give a good indication of how to achieve this:
SELECT a.date,
a.hour,
ISNULL(b.daily, 0) AS daily,
a.hour - ISNULL(b.daily) AS difference
FROM (
SELECT date,
COUNT(*) AS hour
FROM table_a
GROUP BY date
) a
LEFT JOIN (
SELECT date,
COUNT(*) AS daily
FROM table_b
GROUP BY date
) b ON b.date = a.date
ORDER BY a.date;
This works by:
Calculating the count per date in table_a.
Calculating the count per date in table_b.
Joining all results from table_a with those matching in table_b.
Outputting the date, the hour from table_a, the daily (or 0 if NULL) from table_b, and the difference between the two.
Notes:
I have renamed table a and table b to table_a and table_b. I presume these are not the actual table names
An INNER JOIN may be preferable if you only want results that have matching date columns in both tables. Using the LEFT JOIN will return all results from table_a regardless of whether table_b has an entry.
I'm not convinced that date is an allowed column name but I have reproduced it in the code as per the example given by OP.
Your method is fine. Your group by columns are not correct:
Select date, sum(hourly) as hourly, sum(daily) as daily,
sum(hourly) - sum(daily) as diff
from ((select date, count(*) as hourly, 0 as daily
from table a
group by date
) union all
(select date, 0 as hourly, count(*) as daily
from table b
group by date
)
) ab
group by date;
The key idea is that the outer query aggregates only by date -- and you still need aggregation functions there as well.
You have other errors in your subquery, such as missing group bys and date columns. I assume those are transcription errors.

SQL query to sum a column prior to date and show all entries after that date

I have a table where limits were sanctioned to the customer
I am trying to get the output as below picture i.e. total amount sanctioned till particular date
I am trying below code but this sums the total sanction amount
select gam.id, sum(SANCTION_AMOUNT) from gam
join (select ID,ACCOUNT_OPEN_DATE from gam where ACCOUNT_OPEN_DATE between'01-04-2019' and '30-04-2019' AND SCHEME_CODE IN ('SB','CCKLY')) ) action
on( gam.ACCOUNT_OPEN_DATE <=action.ACCOUNT_OPEN_DATE and gam.id=action.cust_id) group by gam.id;
In Oracle, this can be a way:
select id, sanction_amount, scheme_code, account_open_date,
sum(sanction_amount) over (partition BY ID order by account_open_date) as total_sanction_amount
from gam
order by account_open_date
Not sure your database is MySQL or Oracle, But this below script is workable in most of the database. Just adjust the table and column names accordingly.
You can check MySQL DEMO HERE
SELECT *,
(
SELECT SUM(sanction_Amount)
FROM Your_Table B
WHERE B.ID = A.ID
AND B.acc_open_date <= A.acc_open_date
) Total_sanction_Amount
FROM Your_Table A

SQL (BigQuery): How do i use a single value, derived with another query?

This is my query:
WITH last_transaction AS (
SELECT
month
FROM db.transactions
ORDER BY date DESC
LIMIT 1
)
SELECT
*
FROM db.transactions
-- WHERE month = last_transaction.month
WHERE month = 11
GROUP BY
id
Commented out line doesn't work, but intention is clear, i assume: i need to select transactions for the latest month. Business logic might not make sense, because i've extracted it from a bigger query. The main question is: how do i use a single value, derived with another query.
You have only one row, so you can use a scalar subquery:
SELECT t.*
FROM db.transactions t
WHERE month = (SELECT last_transaction.month FROM last_transaction);
I removed the GROUP BY id because it would be a syntax error in BigQuery and it logically does not make sense. Why would a column called id be duplicated in the table?
However, this query would often be written as:
SELECT t.*
FROM (SELECT t.*, MAX(month) OVER () as max_month
FROM db.transactions t
WHERE month = max_month;
Try to JOIN the last_transaction.
A bit like this;
SELECT *
FROM db.transactions
JOIN last_transaction
ON db.transactions.id = last_transaction.id
WHERE month = last_transaction.month
GROUP BY id

How to calculate average users visits per day

I have a requests table which include request data for my my page requests. I have field including Id, UserAgent, Ip, EventDateUtc, etc. How to write SQL which give me average requests per day.
You can get a count grouped by UserAgent,EventDateUtc and then do a AVG on top of it.
SELECT AVG(reccount) avg_count,EventDateUtc
FROM
(
SELECT COUNT(*) reccount,UserAgent, CONVERT(DATE,EventDateUtc) EventDateUtc
FROM PageVisit
GROUP BY CONVERT(DATE,EventDateUtc),UserAgent
)T
GROUP BY EventDateUtc
If you want a total average for all days, don't do a GROUP BY in the outer query.
SELECT AVG(reccount) avg_count
FROM
(
SELECT COUNT(*) reccount,UserAgent, CONVERT(DATE,EventDateUtc) EventDateUtc
FROM PageVisit
GROUP BY CONVERT(DATE,EventDateUtc),UserAgent
)T
The inner select counts visits / day, the outer the average:
select avg(cnt)
from (select count(*) as cnt
from tablename
group by EventDateUtc)

SQL GROUP BY ( DATEPART(), field1 ) result set to zero nulls

I want to aggregate counts, grouped by a datepart and column.
For example, a table with 3 columns with each row representing a unique event: id, name, date
I want to select total counts grouped by name and hour, with zeros when there are no events. If I'm only grouping by name, I can join it with a table of every name. With an hour I could do something similar.
How would I handle the case of grouping by both without having a table with a row for every name+hour combination?
The following is the mysql solution:
create table hours (hour int)
insert hours (hour) values (0), (1) .... (23)
select hour, name, sum(case when name is null then 0 else 1 end)
from hours left outer join
event on (hour(event.date) = hours.hour)
group by hour, name
the sum(case when name is null then 0 else 1 end) handles the case when there are no events for a particular hour and name. the count will show as 0. For others each matching row contributes 1 to the sum.
For sql server use datepart(hour, event.date) instead. The rest should be similar
You can use cross join to generate all the rows and then other logic to fill in the values:
select h.hour, n.name, count(a.name) as cnt
from (select distinct hour(date) as hour from atable) h cross join
(select distinct name from atable) n left join
atable a
on hour(a.date) = h.hour and a.name = n.name
group by h.hour, n.name;