I have the following two tables:
Table TempUser22 : 57,000 rows:
+------+-----------+
| Id | Followers |
+------+-----------+
| 874 | 55542 |
| 1081 | 330624 |
| 1378 | 17919 |
| 1621 | 920 |
| 1688 | 255463 |
| 2953 | 751 |
| 3382 | 204466 |
| 3840 | 273489 |
| 4145 | 376 |
| ... | ... |
+------+-----------+
Table temporal_users : 10,000,000 rows total, 3200 rows Where Date=2010-12-31:
+---------------------+---------+--------------------+
| Date | User_Id | has_original_tweet |
+---------------------+---------+--------------------+
| 2008-02-22 12:00:00 | 676493 | 2 |
| 2008-02-22 12:00:00 | 815263 | 1 |
| 2008-02-22 12:00:00 | 6245822 | 1 |
| 2008-02-22 12:00:00 | 8854092 | 1 |
| 2008-02-23 12:00:00 | 676493 | 2 |
| 2008-02-23 12:00:00 | 815263 | 1 |
| 2008-02-23 12:00:00 | 6245822 | 1 |
| 2008-02-23 12:00:00 | 8854092 | 1 |
| 2008-02-24 12:00:00 | 676493 | 2 |
| ............. | ... | .. |
+---------------------+---------+--------------------+
I am running the following join query on these tables:
SELECT sum(has_original_tweet), b.Id
FROM temporal_users AS a
RIGHT JOIN TempUser22 AS b
ON a.User_ID = b.Id
GROUP BY b.Id;
Which returns 57,00 rows as expected, with NULL answers on the first field:
+-------------------------+------+
| sum(has_original_tweet) | Id |
+-------------------------+------+
| NULL | 874 |
| NULL | 1081 |
| 135 | 1378 |
| 164 | 1621 |
| 652 | 1688 |
| 691 | 2953 |
| NULL | 3382 |
| NULL | 3840 |
| NULL | 4145 |
| ... | .... |
+-------------------------+------+
However, when adding the WHERE line specifying a date as below:
SELECT sum(has_original_tweet), b.Id
FROM temporal_users AS a
RIGHT JOIN TempUser22 AS b
ON a.User_ID = b.Id
WHERE a.Date BETWEEN '2010-12-31-00:00:00' AND '2010-12-31-23:59:59'
GROUP BY b.Id;
I receive the following answer, of only 3200 rows, and without any NULL in the first field.
+-------------------------+---------+
| sum(has_original_tweet) | Id |
+-------------------------+---------+
| 1 | 797194 |
| 1 | 815263 |
| 0 | 820678 |
| 1 | 1427511 |
| 0 | 4653731 |
| 1 | 5933862 |
| 2 | 7530552 |
| 1 | 7674072 |
| 1 | 8149632 |
| .. | .... |
+-------------------------+---------+
My question is: How to get, for a given date, an answer of size 57,000 rows for each user in TempUser22 with NULL values when has_original_tweet is not present in temporal_user for the given date?
Thanks.
SELECT b.Id, SUM(a.has_original_tweet) s
FROM TempUser22 b
LEFT JOIN temporal_users a ON b.Id = a.User_Id
AND a.Date BETWEEN '2010-12-31-00:00:00' AND '2010-12-31-23:59:59'
GROUP BY b.Id;
Id s
1 null
2 1
3 null
4 3
5 null
6 null
For debugging, I used:
CREATE TEMPORARY TABLE TempUser22(Id INT, Followers INT)
SELECT 1 Id, 10 Followers UNION ALL
SELECT 2, 20 UNION ALL
SELECT 3, 30 UNION ALL
SELECT 4, 40 UNION ALL
SELECT 5, 50 UNION ALL
SELECT 6, 60
;
CREATE TEMPORARY TABLE temporal_users(`Date` DATETIME, User_Id INT, has_original_tweet INT)
SELECT '2008-02-22 12:00:00' `Date`, 1 User_Id, 1 has_original_tweet UNION ALL
SELECT '2008-12-31 12:00:00', 2, 1 UNION ALL
SELECT '2010-12-31 12:00:00', 2, 1 UNION ALL
SELECT '2012-12-31 12:00:00', 2, 1 UNION ALL
SELECT '2008-12-31 12:00:00', 4, 9 UNION ALL
SELECT '2010-12-31 12:00:00', 4, 1 UNION ALL
SELECT '2010-12-31 12:00:00', 4, 2 UNION ALL
SELECT '2012-12-31 12:00:00', 4, 9
;
That's because NULL values will always be discarded from the where clause
You can use a coalesce in your where clause.
WHERE coalesce(a.Date, 'some-date-in-the-range') BETWEEN '2010-12-31-00:00:00' AND '2010-12-31-23:59:59'
With this instead, you force null values to be considered as valid.
Related
We have two tables credit_points and debit_points having user_id is reference. Our concern is we want to fetch all the records in a single query order by created_date DESC with limit and offset. Please find the table list and Output table.
credit_points
+----+----------+--------------+---------------------+
| id | user_id | credit_value | created_date |
+----+----------+--------------+---------------------+
| 1 | 111 | 13 | 2020-01-08 10:20:26 |
| 2 | 111 | 11 | 2020-01-09 11:20:23 |
| 3 | 111 | 7 | 2020-01-09 13:25:12 |
| 4 | 111 | 20 | 2020-01-13 12:25:17 |
+----+----------+--------------+---------------------+
debit_points
+----+----------+--------------+---------------------+
| id | user_id | debit_value | created_date |
+----+----------+--------------+---------------------+
| 1 | 111 | 13 | 2020-01-09 10:20:25 |
| 2 | 111 | 11 | 2020-01-11 11:18:54 |
| 3 | 111 | 15 | 2020-01-14 13:50:24 |
| 4 | 111 | 5 | 2020-01-14 15:23:12 |
+----+----------+------------+-----------------------+
Output should be:
+----------+--------------+---+------------------------------+
| user_id | credit_value | debit_value | created_date |
+----------+--------------+-------------+--------------------+
| 111 | NULL | 5 |2020-01-14 15:23:12 |
| 111 | NULL | 15 |2020-01-14 13:50:24 |
| 111 | 20 | NULL |2020-01-13 12:25:17 |
| 111 | NULL | 11 |2020-01-11 11:18:54 |
| 111 | 7 | NULL |2020-01-09 13:25:12 |
| 111 | 11 | NULL |2020-01-09 11:20:23 |
| 111 | NULL | 13 |2020-01-09 10:20:25 |
| 111 | 13 | NULL |2020-01-08 10:20:26 |
+----------+--------------+-------------+-----+--------------+
Query1:
SELECT
c.user_id, c.credit_value, d.debit_value, d.created_date
FROM credit_points c
RIGHT JOIN debit_points d ON(c.user_id=d.user_id)
WHERE c.user_id=111
ORDER BY c.created_date,d.created_date DESC
limit 20;
I know the above query is completely wrong. Please help me to fetch it in the right way.
Query2:
SELECT user_id,credit_value, created_date
FROM credit_points where user_id=111
UNION ALL
SELECT user_id,debit_value,created_date
FROM debit_points where user_id=111 ORDER BY created_date DESC
The above query(Query2) is working fine but we are unable to fetch the debit_value column. Both credit_value and debit_value is coming in one column.
You can combine the data from both tables into a derived table by using UNION and then execute a SELECT over it with needed offset:
SELECT * FROM
(
SELECT user_id, credit_value, NULL AS debit_value, created_date FROM muvi_credit_points
UNION ALL
SELECT user_id, NULL AS credit_value, debit_value, created_date FROM muvi_debit_points
) t
WHERE user_id = 111
ORDER BY created_date DESC
LIMIT 0, 20
Of course, the filtering by user_id could be done into internal SELECT statements if needed.
I have a mysql query that sometimes results in missing values. For my dashboard I'd like to fill those values, but would prefer to avoid build dummy tables if I can.
query:
SELECT COUNT(Comms_Timestamp) as call_count,DAYOFWEEK(Comms_Timestamp) as bucket
FROM tblTest GROUP BY bucket;
results in
+------------+--------+
| call_count | bucket |
+------------+--------+
| 4 | 1 |
| 7 | 2 |
| 7 | 3 |
| 1 | 5 |
| 6 | 6 |
| 1 | 7 |
+------------+--------+
In the above example you can see bucket 4 is missing. I consider the method where the join is to a select union array, however since both fields are aggregates, I'm not sure how to go about it.
test data is
+---------------------+
| Comms_Timestamp |
+---------------------+
| 2018-12-24 06:04:05 |
| 2018-12-24 12:18:39 |
| 2018-12-21 04:24:31 |
| 2018-12-21 08:32:44 |
| 2018-12-30 01:41:06 |
| 2018-12-30 01:53:00 |
| 2018-12-30 01:53:39 |
| 2018-12-30 02:00:01 |
| 2018-12-17 15:55:03 |
| 2018-12-17 16:04:12 |
| 2018-12-17 16:05:41 |
| 2018-12-17 16:07:43 |
| 2018-12-17 16:10:25 |
| 2018-12-18 14:03:22 |
| 2018-12-18 14:03:29 |
| 2018-12-18 14:10:19 |
| 2018-12-18 14:10:29 |
| 2018-12-18 14:10:31 |
| 2018-12-18 14:10:47 |
| 2018-12-18 14:10:55 |
| 2018-12-20 08:21:07 |
| 2018-12-28 11:03:59 |
| 2018-12-28 12:06:40 |
| 2018-12-28 12:15:01 |
| 2018-12-28 14:29:24 |
| 2019-01-05 13:33:43 |
+---------------------+
Since you are using mysql and don't have access to the seq_ option, here is an alternative way:
SELECT A.x AS bucket, IF(ISNULL(COUNT(t2.Comms_Timestamp)), 0, COUNT(t2.Comms_Timestamp)) AS call_count FROM
(select 1 x union select 2 union select 3 union select 4 union select 5 union select 6 union select 7) AS A
LEFT JOIN tblTest AS t2 ON DAYOFWEEK(t2.Comms_Timestamp) = A.x
GROUP BY bucket
ORDER BY bucket;
It may not be the prettiest option but will do what you need.
Here is a db fiddel link: db<>fiddle
If you are using MariaDB there is their Sequence Storage Engine
There is no create needed for this table, however the maximum value must be known.
select version();
| version() |
| :------------------------------------------ |
| 10.3.11-MariaDB-1:10.3.11+maria~stretch-log |
create table bob (a int)
✓
insert into bob values (4),(2)
✓
select * from seq_1_to_5
| seq |
| --: |
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
SELECT s.seq, bob.a
FROM seq_1_to_5 s
LEFT JOIN bob
ON bob.a = s.seq
ORDER BY s.seq
seq | a
--: | ---:
1 | null
2 | 2
3 | null
4 | 4
5 | null
db<>fiddle here
You can use IFNULL() function in MYSQL:
SELECT IFNULL(COUNT(C.Comms_Timestamp),0) as call_count,IFNULL(DAYOFWEEK(C.Comms_Timestamp),0) as bucket
FROM tblCommunication as C LEFT JOIN tblCareTeam as CT on C.id_Case = CT.id_Case
GROUP BY CT.id_Site,bucket
HAVING CT.id_Site=8;
This question already has answers here:
Retrieving the last record in each group - MySQL
(33 answers)
Closed 4 years ago.
I have the following table.
+--------------------+--------------+-------+
Date | SymbolNumber | Value
+--------------------+--------------+-------+
2018-08-31 15:00:00 | 123 | data
2018-09-31 15:00:00 | 456 | data
2018-09-31 15:00:00 | 123 | data
2018-09-31 15:00:00 | 555 | data
2018-10-31 15:00:00 | 555 | data
2018-10-31 15:00:00 | 231 | data
2018-10-31 15:00:00 | 123 | data
2018-11-31 15:00:00 | 123 | data
2018-11-31 15:00:00 | 555 | data
2018-12-31 15:00:00 | 123 | data
2018-12-31 15:00:00 | 555 | data
I need a query that can select the last row of each SymbolNumber stated in the query.
SELECT
*
FROM
MyTable
WHERE
symbolNumber IN (123, 555)
AND
**lastOfRow ordered by latest-date**
Expected results:
2018-12-31 15:00:00 | 123 | data
2018-12-31 15:00:00 | 555 | data
How can I do this?
First, you will need a query that get the latest date for each symbolNumber. Second, you can inner join to this table (using date) for get the rest of the columns. Like this:
SELECT
t.*
FROM
<table_name> AS t
INNER JOIN
(SELECT
symbolNumber,
MAX(date) AS maxDate
FROM
<table_name>
GROUP BY
symbolNumber) AS latest_date ON latest_date.symbolNumber = t.symbolNumber AND latest_date.maxDate = t.date
The previous query will get latest data for each existing symbolNumber on the table. If you want to restrict to symbolNumbers: 123 and 555, you will need to made next modification:
SELECT
t.*
FROM
<table_name> AS t
INNER JOIN
(SELECT
symbolNumber,
MAX(date) AS maxDate
FROM
<table_name>
WHERE
symbolNumber IN (123, 555)
GROUP BY
symbolNumber) AS latest_date ON latest_date.symbolNumber = t.symbolNumber AND latest_date.maxDate = t.date
We can do a "self-left-join" on symbolNumber, and match to other rows in the same group with higher Date value on the right side.
We will eventually consider only those rows, where higher date could not be found (meaning the current row belongs to highest date in the group).
Here is a solution avoiding subquery, and utilizing Left Join:
SELECT t1.*
FROM MyTable AS t1
LEFT JOIN MyTable AS t2
ON t2.symbolNumber = t1.symbolNumber AND
t2.Date > t1.Date -- Joining to a row in same group with higher date
WHERE t1.symbolNumber IN (123, 555) AND
t2.symbolNumber IS NULL -- Higher date not found; so this is highest row
EDIT:
Benchmarking studies comparing Left Join method v/s Derived Table (Subquery)
#Strawberry ran a little benchmark test in 5.6.21. Here's what he found...
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id SERIAL PRIMARY KEY
,dense_user INT NOT NULL
,sparse_user INT NOT NULL
);
INSERT INTO my_table (dense_user,sparse_user)
SELECT RAND()*100,RAND()*100000;
INSERT INTO my_table (dense_user,sparse_user)
SELECT RAND()*100,RAND()*100000 FROM my_table;
-- REPEAT THIS LINE A FEW TIMES !!!
SELECT COUNT(DISTINCT dense_user) dense
, COUNT(DISTINCT sparse_user) sparse
, COUNT(*) total
FROM my_table;
+-------+--------+---------+
| dense | sparse | total |
+-------+--------+---------+
| 101 | 99999 | 1048576 |
+-------+--------+---------+
ALTER TABLE my_table ADD INDEX(dense_user);
ALTER TABLE my_table ADD INDEX(sparse_user);
--dense_test
SELECT x.*
FROM my_table x
LEFT
JOIN my_table y
ON y.dense_user = x.dense_user
AND y.id < x.id
WHERE y.id IS NULL
ORDER
BY dense_user
LIMIT 10;
+------+------------+-------------+
| id | dense_user | sparse_user |
+------+------------+-------------+
| 1212 | 0 | 1950 |
| 153 | 1 | 23193 |
| 255 | 2 | 27472 |
| 28 | 3 | 86440 |
| 18 | 4 | 47886 |
| 291 | 5 | 76563 |
| 15 | 6 | 85049 |
| 16 | 7 | 78384 |
| 135 | 8 | 52304 |
| 62 | 9 | 40930 |
+------+------------+-------------+
10 rows in set (2.64 sec)
SELECT x.*
FROM my_table x
JOIN
( SELECT dense_user, MIN(id) id FROM my_table GROUP BY dense_user ) y
ON y.dense_user = x.dense_user
AND y.id = x.id
ORDER
BY dense_user
LIMIT 10;
+------+------------+-------------+
| id | dense_user | sparse_user |
+------+------------+-------------+
| 1212 | 0 | 1950 |
| 153 | 1 | 23193 |
| 255 | 2 | 27472 |
| 28 | 3 | 86440 |
| 18 | 4 | 47886 |
| 291 | 5 | 76563 |
| 15 | 6 | 85049 |
| 16 | 7 | 78384 |
| 135 | 8 | 52304 |
| 62 | 9 | 40930 |
+------+------------+-------------+
10 rows in set (0.05 sec)
Uncorrelated query is 50 times faster.
--sparse test
SELECT x.*
FROM my_table x
LEFT
JOIN my_table y
ON y.sparse_user = x.sparse_user
AND y.id < x.id
WHERE y.id IS NULL
ORDER
BY sparse_user
LIMIT 10;
+--------+------------+-------------+
| id | dense_user | sparse_user |
+--------+------------+-------------+
| 165055 | 75 | 0 |
| 37598 | 63 | 1 |
| 170596 | 70 | 2 |
| 46142 | 87 | 3 |
| 33546 | 21 | 4 |
| 323114 | 87 | 5 |
| 86592 | 96 | 6 |
| 156711 | 36 | 7 |
| 17148 | 62 | 8 |
| 139965 | 71 | 9 |
+--------+------------+-------------+
10 rows in set (0.03 sec)
SELECT x.*
FROM my_table x
JOIN ( SELECT sparse_user, MIN(id) id FROM my_table GROUP BY sparse_user ) y
ON y.sparse_user = x.sparse_user
AND y.id = x.id
ORDER
BY sparse_user
LIMIT 10;
+--------+------------+-------------+
| id | dense_user | sparse_user |
+--------+------------+-------------+
| 165055 | 75 | 0 |
| 37598 | 63 | 1 |
| 170596 | 70 | 2 |
| 46142 | 87 | 3 |
| 33546 | 21 | 4 |
| 323114 | 87 | 5 |
| 86592 | 96 | 6 |
| 156711 | 36 | 7 |
| 17148 | 62 | 8 |
| 139965 | 71 | 9 |
+--------+------------+-------------+
10 rows in set (4.73 sec)
Exclusion Join is 150 times faster
However, as you move further up the result set, the picture begins to change very dramatically...
SELECT x.*
FROM my_table x
JOIN ( SELECT sparse_user, MIN(id) id FROM my_table GROUP BY sparse_user ) y
ON y.sparse_user = x.sparse_user
AND y.id = x.id
ORDER
BY sparse_user
LIMIT 10000,10;
+--------+------------+-------------+
| id | dense_user | sparse_user |
+--------+------------+-------------+
| 9810 | 93 | 10000 |
| 162438 | 4 | 10001 |
| 467371 | 62 | 10002 |
| 8258 | 13 | 10003 |
| 297049 | 17 | 10004 |
| 68354 | 23 | 10005 |
| 192701 | 64 | 10006 |
| 176225 | 92 | 10007 |
| 156595 | 37 | 10008 |
| 318266 | 1 | 10009 |
+--------+------------+-------------+
10 rows in set (9.17 sec)
SELECT x.*
FROM my_table x
LEFT
JOIN my_table y
ON y.sparse_user = x.sparse_user
AND y.id < x.id
WHERE y.id IS NULL
ORDER
BY sparse_user
LIMIT 10000,10;
+--------+------------+-------------+
| id | dense_user | sparse_user |
+--------+------------+-------------+
| 9810 | 93 | 10000 |
| 162438 | 4 | 10001 |
| 467371 | 62 | 10002 |
| 8258 | 13 | 10003 |
| 297049 | 17 | 10004 |
| 68354 | 23 | 10005 |
| 192701 | 64 | 10006 |
| 176225 | 92 | 10007 |
| 156595 | 37 | 10008 |
| 318266 | 1 | 10009 |
+--------+------------+-------------+
10 rows in set (32.19 sec) -- !!!
In summary, the exclusion join (the so-called 'strawberry query' can be (significantly) faster in certain, limited situations. More generally, an uncorrelated query will be faster.
I have the following tables structure and trying to make a report from these:
___BillableDatas
|--------|------------|---------|--------------|------------|
| BIL_Id | BIL_Date |BIL_Rate | BIL_Quantity | BIL_Status |
|--------|------------|---------|--------------|------------|
| 1 | 2018-03-01 | 105 | 1 | charged |
| 2 | 2018-03-02 | 105 | 1 | cancelled |
| 3 | 2018-03-01 | 15 | 2 | notcharged |
| 4 | 2018-03-01 | 21 | 1 | notcharged |
| 5 | 2018-03-02 | 15 | 2 | notcharged |
| 6 | 2018-03-02 | 21 | 1 | notcharged |
|--------|------------|---------|--------------|------------|
___SalesTaxes
|--------|--------------|------------|
| STX_Id | STX_TaxeName | STX_Amount |
|--------|--------------|------------|
| 8 | Tax 1 | 5.000 |
| 9 | Tax 2 | 5.000 |
| 10 | Tax 3 | 19.975 |
|--------|--------------|------------|
STX_Amount is a percentage.
___ApplicableTaxes
|-----------|-----------|
| ATX_BILId | ATX_STXId |
|-----------|-----------|
| 1 | 8 |
| 1 | 9 |
| 1 | 10 |
| 2 | 8 |
| 2 | 9 |
| 2 | 10 |
| 3 | 9 |
| 3 | 10 |
| 4 | 9 |
| 5 | 9 |
| 5 | 10 |
| 6 | 9 |
|-----------|-----------|
ATX_BILId is the item ID link with ___BillableDatas.
ATX_STXId is the tax ID link with ___SalesTaxes.
I need to get to sum of the items per day
- without tax
- with tax
So mething like this:
|------------------|---------------|------------|
| BIL_RateNonTaxed | BIL_RateTaxed | BIL_Status |
|------------------|---------------|------------|
| 105.00 | 136.47 | charged | <- Taxes #8, #9 and #10 applicable
| 102.00 | 118.035 | notcharged | <- Taxes #9 and #10 applicable
|------------------|---------------|------------|
Explications on the totals:
105 = 105*1 -- (total of the charged item multiply by the quantity)
102 = (15*2)*2+(21*2) -- (total of the notcharged items multiply by the quantity)
136.47 = 105+(105*(5+5+19.975)/100)
119.085 = 102+(((15*2)*2)*(5+19.975)/100+(21*2)*5/100)
My last try was this one:
SELECT
BIL_Date,
(BIL_Rate*BIL_Quantity) AS BIL_RateNonTaxed,
(((BIL_Rate*BIL_Quantity)*SUM(STX_Amount)/100)+BIL_Rate*BIL_Quantity) AS BIL_RateTaxed,
BIL_Status
FROM ___BillableDatas
LEFT JOIN ___SalesTaxes
ON FIND_IN_SET(STX_Id, BIL_ApplicableTaxes) > 0
LEFT JOIN ___ApplicableTaxes
ON ___BillableDatas.BIL_Id = ___ApplicableTaxes.ATX_BILId
WHERE BIL_BookingId=1
GROUP BY BIL_Id AND BIL_Status
ORDER BY BIL_Date
ASC
Please see this SQLFiddle to help you if needed:
http://sqlfiddle.com/#!9/425854f
Thanks.
I cannot bear to work with your naming policy, so I made my own...
DROP TABLE IF EXISTS bills;
CREATE TABLE bills
(bill_id SERIAL PRIMARY KEY
,bill_date DATE NOT NULL
,bill_rate INT NOT NULL
,bill_quantity INT NOT NULL
,bill_status ENUM('charged','cancelled','notcharged')
);
INSERT INTO bills VALUES
(1,'2018-03-01',105,1,'charged'),
(2,'2018-03-02',105,1,'cancelled'),
(3,'2018-03-01',15,2,'notcharged'),
(4,'2018-03-01',21,1,'notcharged'),
(5,'2018-03-02',15,2,'notcharged'),
(6,'2018-03-02',21,1,'notcharged');
DROP TABLE IF EXISTS sales_taxes;
CREATE TABLE sales_taxes
(sales_tax_id SERIAL PRIMARY KEY
,sales_tax_name VARCHAR(12) NOT NULL
,sales_tax_amount DECIMAL(5,3) NOT NULL
);
INSERT INTO sales_taxes VALUES
( 8,'Tax 1', 5.000),
( 9,'Tax 2', 5.000),
(10,'Tax 3',19.975);
DROP TABLE IF EXISTS applicable_taxes;
CREATE TABLE applicable_taxes
(bill_id INT NOT NULL
,sales_tax_id INT NOT NULL
,PRIMARY KEY(bill_id,sales_tax_id)
);
INSERT INTO applicable_taxes VALUES
(1, 8),
(1, 9),
(1,10),
(2, 8),
(2, 9),
(2,10),
(3, 9),
(3,10),
(4, 9),
(5, 9),
(5,10),
(6, 9);
SELECT bill_status
, SUM(bill_rate*bill_quantity) nontaxed
, SUM((bill_rate*bill_quantity)+(bill_rate*bill_quantity*total_sales_tax/100)) taxed
FROM
( SELECT b.*
, SUM(t.sales_tax_amount) total_sales_tax
FROM bills b
JOIN applicable_taxes bt
ON bt.bill_id = b.bill_id
JOIN sales_taxes t
ON t.sales_tax_id = bt.sales_tax_id
GROUP
BY bill_id
) x
GROUP
BY bill_status;
+-------------+---------+-------------+
| bill_status | untaxed | total |
+-------------+---------+-------------+
| charged | 105 | 136.4737500 |
| cancelled | 105 | 136.4737500 |
| notcharged | 102 | 119.0850000 |
+-------------+---------+-------------+
My answer is very slightly different from yours, so one of us has made a mistake somewhere. Either way, this should get you pretty close.
SELECT a.BIL_Date, BIL_RateNonTaxed, BIL_RateNonTaxed+BIL_RateTaxed AS BIL_RateTaxed FROM (
SELECT BIL_Date,
SUM(BIL_Rate*BIL_Quantity) AS BIL_RateNonTaxed
FROM ___BillableDatas
WHERE BIL_Status != 'cancelled'
GROUP BY BIL_Date
) a INNER JOIN (
SELECT BIL_Date,
(((BIL_Rate*BIL_Quantity)*SUM(STX_Amount)/100)) AS BIL_RateTaxed
FROM ___BillableDatas
LEFT JOIN ___ApplicableTaxes
ON ___BillableDatas.BIL_Id = ___ApplicableTaxes.ATX_BILId
LEFT JOIN ___SalesTaxes
ON STX_Id = ATX_STXId
WHERE BIL_Status != 'cancelled'
GROUP BY BIL_Date
) b
ON a.BIL_Date = b.BIL_Date
ORDER BY a.BIL_Date;
Explanation:
Your BIL_RateNonTaxed calculation is not using the ___SalesTaxes table, so it must not appear on the query otherwise it would interfere the SUM function.
Howerver, your BIL_RateTaxed does use the ___SalesTaxes table. In that case, I solved by creating 2 subqueries and joining the results.
I know there are better answers, but I'm not familiar with MySQL syntax.
+-----------+-----------+--------+
| punchtime | punchdate | emp_id |
+-----------+-----------+--------+
| 9:51:00 | 4/1/2016 | 2 |
| 12:59:00 | 4/1/2016 | 2 |
| 10:28:00 | 4/1/2016 | 5 |
| 14:13:00 | 4/1/2016 | 5 |
| 9:56:00 | 4/1/2016 | 10 |
| 15:31:00 | 4/1/2016 | 10 |
| 10:08:00 | 5/1/2016 | 2 |
| 18:09:00 | 5/1/2016 | 2 |
| 10:15:00 | 5/1/2016 | 5 |
| 18:32:00 | 5/1/2016 | 5 |
| 10:11:00 | 6/1/2016 | 2 |
| 18:11:00 | 6/1/2016 | 2 |
| 10:25:00 | 6/1/2016 | 5 |
| 18:28:00 | 6/1/2016 | 5 |
| 10:19:00 | 6/1/2016 | 10 |
| 18:26:00 | 6/1/2016 | 10 |
+-----------+-----------+--------+
I need to count where emp_id punchtime is less then that 4 hours and count ir for the whole. i am trying the below code but its not working.
SELECT
a.emp_id,
sum( case when TIMESTAMPDIFF(hour, min(a.punchtime),
max(a.punchtime))< 4 then 1 else 0 end ) as 'Half Day'
FROM machinedata a
GROUP BY
a.emp_id
I am getting a error #1111 - Invalid use of group function
Desired output -
+-----------+-----------+
| emp_id | Half Day |
+-----------+-----------+
|2 | 1 |
|8 | 0 |
|10 |0 |
+-----------+-----------+
Your data set and desired result do not accord, so I'm going to ignore it...
Instead consider the following...
Note both the way in which I have presented the problem, and the construction of the solution.
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(employee_id INT NOT NULL
,punchtime DATETIME NOT NULL
,PRIMARY KEY(employee_id,punchtime)
);
INSERT INTO my_table VALUES
( 2,'2016/01/04 09:51:00'),
( 2,'2016/01/04 12:59:00'),
( 5,'2016/01/04 10:28:00'),
( 5,'2016/01/04 14:13:00'),
(10,'2016/01/04 09:56:00'),
(10,'2016/01/04 15:31:00'),
( 2,'2016/01/05 10:08:00'),
( 2,'2016/01/05 18:09:00'),
( 5,'2016/01/05 10:15:00'),
( 5,'2016/01/05 18:32:00'),
( 2,'2016/01/06 10:11:00'),
( 2,'2016/01/06 18:11:00'),
( 5,'2016/01/06 10:25:00'),
( 5,'2016/01/06 18:28:00'),
(10,'2016/01/06 10:19:00'),
(10,'2016/01/06 18:26:00');
SELECT employee_id
, SUM(diff < 14400 ) half
FROM
( SELECT x.*
, DATE(x.punchtime) dt
, TIME_TO_SEC(MAX(y.punchtime)) - TIME_TO_SEC(MIN(x.punchtime)) diff
FROM my_table x
JOIN my_table y
ON y.employee_id = x.employee_id
AND DATE(y.punchtime) = DATE(x.punchtime)
GROUP
BY x.employee_id
, dt
) n
GROUP
BY employee_id;
+-------------+------+
| employee_id | half |
+-------------+------+
| 2 | 1 |
| 5 | 1 |
| 10 | 0 |
+-------------+------+