Total number of records and their reason SQL Server - sql

I want to write a query that get total number of records (booking) using the COUNT(*) function. I have a column Type in the database and in the next column I want to show type of record e.g output of query be like
Total Booking -> 10
Booking Type -> 3 wedding ceremony, 4 Birthday Party, 3 family Event (this will be in single cell next to total Booking)
Someone please help me.. Thanks

Try this out, it will give you the total count of each type, with an overall total at the top.
SELECT 'Total Bookings', COUNT(*)
FROM BookingTable
UNION
SELECT [Type], COUNT(*)
FROM BookingTable
GROUP BY [Type]

Related

Calculating the percentage of different types of customer feedback in each quarter

The problem statement is: I have a table (order_t) which has customer feedback (one column) and quarter number (as another column).
Using a CTE, I need to calculate the percentage of number of customer feedback in each category as well as the total number of customer feedback in each quarter.
After this happens, I need the percentage of different types of customer feedback (like good, bad, ok, very good, very bad) but using CTE.
How can I solve this statement?
I try to solve customer feedback as
WITH total_feedback AS
(
SELECT *
COUNT(CUSTOMER_FEEDBACK), QUARTER NUMBER
FROM
table1
GROUP BY
2
)
But I'm unable to calculate the first half portion, i.e. percentage of different types of customer feedback in each quarter using CTE.
How can I do that?
Find the file of the data
What you could do, and I'll keep the example as close to the code you provided as possible, is the following - using 2 CTE's:
WITH total_feedback AS (
SELECT COUNT(CUSTOMER_FEEDBACK) AS total_feedback, QUARTER_NUMBER
FROM table1
GROUP BY 2
),
category_feedback AS (
SELECT COUNT(CUSTOMER_FEEDBACK) AS feedback_count, CUSTOMER_FEEDBACK, QUARTER_NUMBER
FROM table1
GROUP BY 2, 3
)
SELECT
category_feedback.CUSTOMER_FEEDBACK,
category_feedback.QUARTER_NUMBER,
(feedback_count / total_feedback.total_feedback) * 100 AS feedback_percentage
FROM category_feedback
INNER JOIN total_feedback
ON category_feedback.QUARTER_NUMBER = total_feedback.QUARTER_NUMBER

Find most recent date of purchase in user day table

I'm trying to put together a query that will fetch the date, purchase amount, and number of transactions of the last time each user made a purchase. I am pulling from a user day table that contains a row for each time a user does anything in the app, purchase or not. Basically all I am trying to get is the most recent date in which the number of transactions field was greater than zero. The below query returns all days of purchase made by a particular user when all I'm looking for is the last purchase so just the 1st row shown in the attached screenshot is what I am trying to get.
screen shot of query and result set
select tuid, max(event_day),
purchases_day_rev as last_dop_rev,
purchases_day_num as last_dop_quantity,
purchases_day_rev/nullif(purchases_day_num,0) as last_dop_spend_pp
from
(select tuid, event_day,purchases_day_rev,purchases_day_num
from
app.user_day
where purchases_day_num > 0
and tuid='122d665e-1d71-4319-bb0d-05c7f37a28b0'
group by 1,2,3,4) a
group by 1,3,4,5
I'm not going to comment on the logic of your query... if all you want is the first row of your result set, you can try:
<your query here> ORDER BY 2 DESC LIMIT 1 ;
Where ORDER BY 2 DESC orders the result set on max(event_day) and LIMIT 1 extracts only the first row.
I don't know all of the ins and outs of your data, but I don't understand why you are grouping within the subquery without any aggregate function (sum, average, min, max, etc). With that said, I would try something like this:
select tuid
,event_day
,purchases_day_rev as last_dop_rev
,purchases_day_num as last_dop_quantity
,purchases_day_rev/nullif(purchases_day_num,0) as last_day_spend_pp
from app.user_day a
inner join
(
select tuid
,max(event_day) as MAX_DAY
from app.user_day
where purchases_day_num > 0
and tuid='122d665e-1d71-4319-bb0d-05c7f37a28b0'
group by 1
) b
on a.tuid = b.tuid
and a.event_day = b.max_day;

MS Access Query to records with same data in different fields in the same row

The title is a bit confusing but I'll explain my problem here:
So i have a database table with millions of lines of spending data broken up into different time fields (period1 - period14). Now what i need to do is write a query that will return the records where the spending in one period is equal to the spending in a different period within the same record. So basically that means if i have a reecord where the spending in period1 is $100 and then the spending in period5 is also $100, it will add that record to a new table. I tried something like the code below but since I'm very new to access it is rather complex/inefficient and also doesn't do what i need it to.
INSERT INTO Contracts
SELECT *
FROM SPENDDETAIL
WHERE (SPENDDETAIL.Period1 = SPENDDETAIL.Period2 OR SPENDDETAIL.Period3 [...] OR SPENDDETAIL.Period14)
AND (SPENDDETAIL.Period1 <> 0 OR SPENDDETAIL.Period2 <> 0 [...] OR SPENDDETAIL.Period14 <> 0);
Any help much appreciated, thanks!
Oh also i know this code snippet would only return the records where the period1 spend equals the spend from any of the other periods it was just a beginning attempt at making the query do what i need it to.
Something along these lines might get you started:
SELECT Id, Value, COUNT(*) FROM
(SELECT Id AS Id, 1 AS Period, Period1 AS Value FROM SPENDDETAIL
UNION ALL
SELECT Id AS Id, 2 AS Period, Period2 AS Value FROM SPENDDETAIL
UNION ALL
SELECT Id AS Id 3 AS Period, Period3 AS Value FROM SPENDDETAIL
etc...) x
GROUP BY Id, Value
HAVING COUNT(*) > 1
Where Id is some unique identifier for each row of the data (assuming there is such a thing).
This will give you a list of Ids and matching values.

SQL for statement of accounts

I would like to thank in advance for any help.
My problem relates to two tables in MySQL (Now switching to postgresql). The tables are related to a ticketing database.
a) booking. It has four columns ccode,date,time,amount
b) account It has three columns ccode,date,amount
The booking table has ticket bookings and account table has advances and payments received.
I have to prepare a statement of account based on ccode (customer code).
The statement shows columns as below
*Ccode Type Date time amount balance*
- the report in sorted on ccode and then on date (account table row appears first)
- Type column displays B or A depending on record type
- Time column is present only in booking table
- Report has a running balance for each row
- At the end for a customercode, the totals of amount and balance is displayed
I have had success, so far in creating a join as below. (and after dicussion below, have been able to generate TYPE column using IF)
SELECT booking.cname, booking.bdate, booking.btime, booking.rate, booking.ID,
IF(booking.btime IS NOT NULL, "B", "A") AS type, account.cname, account.date,
account.amount, account.ID
FROM booking
LEFT JOIN account ON booking.bdate = account.date AND booking.cname=account.cname AND
booking.rate = account.amount
UNION
SELECT booking.cname, booking.bdate, booking.btime, booking.rate, booking.ID,
IF(booking.btime IS NOT NULL, "B", "A") AS type, account.cname, account.date,
account.amount, account.ID
FROM booking
RIGHT JOIN account ON booking.bdate = account.date AND booking.cname=account.cname AND
booking.rate = account.amount
It displays all the records. A report can be generated using this table.
But is there a way to display the formatted report just by SQL.
I can change the order of columns and even add or remove existing ones as long as Record type is known and a running balance is displayed against each record.
A SAMPLE REPORT ---- REPORT A
CODE DATE TYPE AMOUNT BALANCE TIME
A1 02/19/2011 A 50 50
A1 02/20/2011 B 35 15 1230
A1 02/21/2011 A 40 55
A1 02/21/2011 B 20 35 1830
optional > TOTAL Account = 90 Booking = 55 Balance = 35
A SAMPLE REPORT ---- REPORT B
CODE AMOUNT BOOKED AMOUNT PAID BALANCE
A1 50 50 0
A1 35 15 20
A1 40 55 -15
A1 20 35 -15
this is a weekly statement version of REPORT A.
the reason is i can add where and between to get only records in a given week.
and since it is a weekly report, running balance is just omitted.
It is report grouped for all entries with customercode A1 present
in booking and account tables.
thanx
Since your data is not normalized for this, you pay the price in query complexity, as shown below:
SELECT ccode, date, time, type, amount,
(SELECT SUM(amount) AS balance
FROM numbered AS n
WHERE numbered.rownum <= n.rownum AND numbered.ccode = n.ccode) AS balance
FROM (SELECT sorted.*, #rownum := #rownum + 1 AS rownum
FROM (SELECT *
FROM (SELECT ccode, date, time, 'B' AS type, amount
FROM booking
UNION
SELECT ccode, date, "0000" AS time, 'A' AS type, -amount
FROM account) AS unsorted
ORDER BY ccode, date, time, type) AS sorted) AS numbered
The idea here is that you first need to get your booking (debits) and account (credits) lined up as in the "unsorted" statement above. Then, you need to sort them by date and time as in the "sorted" statement. Next, add row numbers to the results as in the "numbered" statement. Finally, select all that data along with a sum of amounts with row number less than or equal to the current row number that matches your ccode.
In the future, please consider using a transaction table of some sort which holds all account balance changes in a single table.
I have found the answer.
It is to use cummulative sql statement to find a running balance

sql to calculate daily totals minues the previous day's totals

I have a table that has a date, item, and quantity.
I need a sql query to return the totals per day, but the total is the quantity minus the previous day totals. The quantity accumulates as the month goes on. So the 1st could have 5 the 2nd have 12 and the 3rd has 20.
So the 1st adds 5
2nd adds 7 to make 12
3rd adds 8 to make 20.
I've done something like this in the past, but can not find it or remember. I know i'll need a correlated sub-query.
TIA
--
Edit 1
I'm using Microsoft Access.
Date is a datetime field,
item is a text, and
quantity is number
--
Edit 2
Ok this is what i have
SELECT oos.report_date, oos.tech, oos.total_cpe, oos_2.total_cpe
FROM oos INNER JOIN (
SELECT oos_2.tech, Sum(oos_2.total_cpe) AS total_cpe
FROM oos_2
WHERE (((oos_2.report_date)<#10/10/2010#))
GROUP BY oos_2.tech
) oos_2 ON oos.tech = oos_2.tech;
How do i get the oos.report_date into where i says #10/10/2010#. I thought I could just stick it in there like mysql, but no luck. I'm gonna continue researching.
Sum them by adding one to the date and making the value negative, thus taking yesterday's total from today's:
SELECT report_date, tech, Sum(total_cpe) AS total_cpe
FROM (
SELECT oos.report_date, oos.tech, oos.total_cpe
FROM oos
UNION ALL
SELECT oos.report_date+1, oos.tech, 0-oos.total_cpe
FROM oos
)
WHERE (report_date < #10/10/2010#)
GROUP BY report_date, tech
ORDER BY report_date, tech
Ok, I figured it out.
SELECT o.report_date, o.tech, o.total_cpe,
o.total_cpe - (
SELECT IIf(Sum(oos.total_cpe) is null, 0,Sum(oos.total_cpe)) AS total_cpe
FROM oos
WHERE (((oos.tech)=o.tech) AND ((oos.report_date)<o.report_date))
) AS total
FROM oos o;