SQL Server: count transaction - sql-server-2008

I have this table in SQL Server:
I want a result like this
I am going to write SQL queries to count the transaction and consolidate every month.
Thank you in advance.

First, you need to edit the column you want to group.
SELECT
A.YYYYMM,
COUNT(*) TxnCount
FROM
(
SELECT
*,
LEFT(TXN_DATE, 6) YYYYMM
FROM
Tbl
) A
GROUP BY
A.YYYYMM

Use Group By and Substring :
SELECT
SUBSTRING(CAST(TXNDate AS VARCHAR(12)),0,9) AS TXNDate,COUNT(*) AS 'TXN Count'
FROM
#tblTest
GROUP BY SUBSTRING(CAST(TXNDate AS VARCHAR(12)),0,9)

You can use GROUP BY clause to count the transaction.
Assuming your TXN Date is of date type, you can use following query:
SELECT CONVERT(VARCHAR(6), TXN_DATE, 112) AS YYYYMM, COUNT(*) AS TXN_COUNT
FROM MyTable
GROUP BY CONVERT(VARCHAR(6), TXN_DATE, 112)
ORDER BY CONVERT(VARCHAR(6), TXN_DATE, 112)
EDIT: since your TXN_DATE is int type, you can use the following
SELECT LEFT(CONVERT(VARCHAR, TXN_DATE), 6) AS YYYYMM, COUNT(*) AS TXN_COUNT
FROM MyTable
GROUP BY LEFT(CONVERT(VARCHAR, TXN_DATE), 6)
ORDER BY LEFT(CONVERT(VARCHAR, TXN_DATE), 6)

Related

order by with union in SQL is not working

Is it possible to order when the data comes from many select and union it together? Such as
In this statement, the vouchers data is not showing in the same sequence as I saved on the database, I also tried it with "ORDER BY v_payments.payment_id ASC" but won't be worked
( SELECT order_id as id, order_date as date, ... , time FROM orders WHERE client_code = '$searchId' AND order_status = 1 AND order_date BETWEEN '$start_date' AND '$end_date' ORDER BY time)
UNION
( SELECT vouchers.voucher_id as id, vouchers.payment_date as date, v_payments.account_name as name, ac_balance as oldBalance, v_payments.debit as debitAmount, v_payments.description as descriptions,
vouchers.v_no as v_no, vouchers.v_type as v_type, v_payments.credit as creditAmount, time, zero as tax, zero as freightAmount FROM vouchers INNER JOIN v_payments
ON vouchers.voucher_id = v_payments.voucher_id WHERE v_payments.client_code = '$searchId' AND voucher_status = 1 AND vouchers.payment_date BETWEEN '$start_date' AND '$end_date' ORDER BY v_payments.payment_id ASC , time )
UNION
( SELECT return_id as id, return_date as date, ... , time FROM w_return WHERE client_code = '$searchId' AND w_return_status = 1 AND return_date BETWEEN '$start_date' AND '$end_date' ORDER BY time)
Wrap the sub-select queries in the union within a SELECT
SELECT id, name
FROM
(
SELECT id, name FROM fruits
UNION
SELECT id, name FROM vegetables
)
foods
ORDER BY name
If you want the order to only apply to one of the sub-selects, use parentheses as you are doing.
Note that depending on your DB, the syntax may differ here. And if that's the case, you may get better help by specifying what DB server (MySQL, SQL Server, etc.) you are using and any error messages that result.
You need to put the ORDER BY at the end of the statement i.e. you are ordering the final resultset after union-ing the 3 intermediate resultsets
To use an ORDER BY or LIMIT clause to sort or limit the entire UNION result, parenthesize the individual SELECT statements and place the ORDER BY or LIMIT after the last one. See link below:
ORDER BY and LIMIT in Unions
(SELECT a FROM t1 WHERE a=10 AND B=1)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2)
ORDER BY a LIMIT 10;

How to get total number of records sql daily

I am currently doing to get the count,
Select count(*) from MyTable WHERE ATTEMPT_DATE='01/JUNE/19';
Select count(*) from MyTable WHERE ATTEMPT_DATE='02/JUNE/19';
.
.
Select count(*) from MyTable WHERE ATTEMPT_DATE='30/JUNE/19';
Is there any way to get all the SUM of ( count(*) all dates)
You can use aggregation:
select ATTEMPT_DATE, count(*)
from MyTable
group by ATTEMPT_DATE;
If you want to counts dates within a range, use where:
select count(*)
from MyTable
where ATTEMPT_DATE in ('01/JUNE/19', . . . '30/JUNE/19');
You are using a non-standard date format. If this were a standard date format (or if the column really is a date/datetime value), then I would suggest inequalities rather than in.
Why don't you use direct count(*)
Select count(*) from MyTable WHERE ATTEMPT_DATE BETWEEN '01/JUNE/19' AND '30/JUNE/19'
for datewise count use group by
Select ATTEMPT_DATE, count(*) from MyTable
WHERE ATTEMPT_DATE BETWEEN '01/JUNE/19' AND '30/JUNE/19' group by ATTEMPT_DATE
Cheers!!

MySQL - join query results vertically

I am trying to create a summary report for to capture daily stats. Basically I need the outcome similar to:
Table_Name Updated_Rows Created_Rows Date
Table 1 10 5 2019-04-23
Table 2 17 55 2019-04-23
Now I can fetch the individual values using basic commands:
select count(*) as created_rows
from accounts
where date(updated_at) = date(now())
and
select count(*) as created_rows
from accounts
where date(created_at) = date(now())
Can also combine the data using the UNINON ALL,
(SELECT table_name FROM information_schema.tables where table_name='accounts')
UNION ALL
(select count(*) as created_rows from accounts where date(created_at) = date(now()))
UNION ALL
(select count(*) as updated_rows from accounts where date(updated_at) = date(now()))
However the output I get is kind of stacked vertically and I wish to retain the labels/column names and would want to add data row by row for all the tables I want to assess.
I am sure there is an easier way but I can't seem the find a way out to get this done. Don't need the final query, just help me with a direction to look towards.
For a single table, you can do the following:
SELECT 'account' AS 'Table_Name'
, SUM(date(updated_at) = date(now())) 'Updated_Rows'
, SUM(date(created_at) = date(now())) 'Created_Rows'
, date(now()) AS 'Date'
FROM accounts
where SUM(date(updated_at) = date(now())) is basically the same as
IF(SUM(date(updated_at) = date(now())), 1, 0)
Then UNION ALL result from other tables with the similar query.
You could try something like the following (untested):
select '#x' as table_name,
(select count(*) FROM #x and date(created_at) = date(now())) as created_rows,
(select count(*) FROM #x and date(updated_at) = date(now())) as updated_rows
As part of a prepared statement (https://dev.mysql.com/doc/refman/5.6/en/sql-syntax-prepared-statements.html) or proc (https://medium.com/#peter.lafferty/mysql-stored-procedures-101-6b4fe230967) or just union to get multiple tables (note that you'd have to change some syntax). I'm not sure how you need to run this, so I'm not sure what exactly you need, what kind of performance you're after, if you're just going to make a script and manually select the tables or if you're trying to run this on all tables, etc.
EDIT: jxc's query is much better than mine!
Is this what you are looking for? If so, make sure to change the table names in the subsequent UNION ALL queries.
SELECT
'accounts' AS TableName,
SUM(DATE(updated_at) = DATE(NOW())) AS updated_rows,
SUM(DATE(created_at) = DATE(NOW())) AS created_rows,
DATE(NOW()) AS `Date`
FROM
accounts
UNION ALL
SELECT
'accounts2' AS TableName,
SUM(DATE(updated_at) = DATE(NOW())) AS updated_rows,
SUM(DATE(created_at) = DATE(NOW())) AS created_rows,
DATE(NOW()) AS `Date`
FROM
accounts2
and so forth....
EDIT This query is identical to jxc's query posted earlier

MySQL aggregate sum of count

I have a simple group by query:
SELECT timestamp, COUNT(users)
FROM my_table
GROUP BY users
How do I add a sum_each_day column that will sum the users count of each row and will aggregate it forward to the next row and so on
The output should be like this:
timestamp | users | sum_each_day
2015-11-27 1 1
2015-11-28 5 6
2015-11-29 3 9
2015-11-30 7 16
Thanks in advance
You could use a sub-query, like this:
SELECT timestamp,
num_users,
(SELECT COUNT(users)
FROM my_table
WHERE timestamp <= main.timestamp) sum_users
FROM (
SELECT timestamp,
COUNT(users) num_users
FROM my_table
GROUP BY timestamp
) main
If you really need this in mysql it'll cost some performance but i believe a sub query with a count will solve it:
SELECT t1.timestamp, count (), select count () from my_table t2 where t2.timestamp <= t1.timestamp From my_table t1 Group by users
If you display this data through a scripting language like PHP it would be easier to keep a counter and display the aggregate per row.
I would do this using variable:
SET #total := 0;
SELECT timestamp, DayCount, (#total := #total + DayCount) AS Total
FROM
(SELECT timestamp, COUNT(users) AS DayCount
FROM my_table
GROUP BY timestamp) AS t1
Fiddler: I am not using your table structure here, but you can get idea
If I understand correclty, this will work:
set #c=0;
SELECT `timestamp`,sum(`users`),(select #c:=#c+sum(`users`))
FROM `my_table`
group by `timestamp`;

SQL query that finds a negative change between two rows with the same name field

I have a single table with rows like this: (Date, Score, Name)
The Date field has two possible dates, and it's possible that a Name value will appear under only one date (if that name was recently added or removed).
I'm looking to get a table with rows like this: (Delta, Name), where delta is the score change for each name between the earlier and later dates. In addition, only a negative change interests me, so if Delta>=0, it shouldn't appear in the output table at all.
My main challenge for me is calculating the Delta field.
As stated in the title, it should be an SQL query.
Thanks in advance for any help!
I assumed that each name can have it's own start/end dates. It can be simplified significantly if there are only two possible dates for the entire table.
I tried this out in SQL Fiddle here
SELECT (score_end - score_start) delta, name_start
FROM
( SELECT date date_start, score score_start, name name_start
FROM t t
WHERE NOT EXISTS
( SELECT 1
FROM t x
WHERE x.date < t.date
AND x.name = t.name
)
) AS start_date_t
JOIN
( SELECT date date_end, score score_end, name name_end
FROM t t
WHERE NOT EXISTS
( SELECT 1
FROM t x
WHERE x.date > t.date
AND x.name = t.name
)
) end_date_t ON start_date_t.name_start = end_date_t.name_end
WHERE score_end-score_start < 0
lets say you have a table with date_value, sum_value
Then it should be something like that:
select t.date_value,sum_value,
sum_value - COALESCE((
select top 1 sum_value
from tmp_num
where date_value > t.date_value
order by date_value
),0) as sum_change
from tmp_num as t
order by t.date_value
The following uses a "trick" in MySQL that I don't really like using, because it turns the score into a string and then back into a number. But, it is an easy way to get what you want:
select t.name, (lastscore - firstscore) as diff
from (select t.name,
substring_index(group_concat(score order by date asc), ',', 1) as firstscore,
substring_index(group_concat(score order by date desc), ',', 1) as lastscore
from table t
group by t.name
) t
where lastscore - firstscore < 0;
If MySQL supported window functions, such tricks wouldn't be necessary.