I need a count of NULL from 2 tables that are joined in MySQL. Sample data like this:
datefield FROM TABLE calendar (contain dates from start to end of this year)
-----------
TABLE value (data stored)
+------------+-------+
| date | keter |
+------------+-------+
| 2021-08-01 | 11 |
| 2021-08-04 | 0 |
| 2021-08-07 | 20 |
| 2021-08-08 | 15 |
| 2021-08-11 | 0 |
+------------+-------+
I am using the following query to combine and display data from calendar and value tables.
SELECT datefield,keter FROM calendar
LEFT JOIN kehadiran ON datefield=tgl AND id_kar IN ('110101')
WHERE datefield BETWEEN '2021-08-01' AND '2021-08-15' GROUP BY datefield;
result :
+------------+-------+
| datefield | keter |
+------------+-------+
| 2021-08-01 | 11 |
| 2021-08-02 | NULL |
| 2021-08-03 | NULL |
| 2021-08-04 | 0 |
| 2021-08-05 | NULL |
| 2021-08-06 | NULL |
| 2021-08-07 | 20 |
| 2021-08-08 | 15 |
| 2021-08-09 | NULL |
| 2021-08-10 | NULL |
| 2021-08-11 | 0 |
| 2021-08-12 | NULL |
| 2021-08-13 | NULL |
| 2021-08-14 | NULL |
| 2021-08-15 | NULL |
+------------+-------+
I use query based on this question (3 table join counting nulls), I didn't get the result I wanted. The query is this :
SELECT SUM(k.keter) FROM kehadiran k
LEFT OUTER JOIN calendar c ON c.datefield = k.keter AND id_kar IN ('110101')
WHERE datefield BETWEEN '2021-08-01' AND '2021-08-12' AND k.keter is NULL;
result:
+--------------+
| SUM(k.keter) |
+--------------+
| NULL |
+--------------+
the result i wanted :
+--------------+
| SUM(k.keter) |
+--------------+
| 10 |
+--------------+
How should I count NULL from the joined table as mentioned above?
You swapped the tables in your last query which is incorrect. Use the query that worked and use COUNT(*) with WHERE right_table.any_notnull_column IS NULL:
SELECT COUNT(*)
FROM calendar
LEFT JOIN kehadiran k ON datefield=tgl AND id_kar IN ('110101')
WHERE datefield BETWEEN '2021-08-01' AND '2021-08-15'
AND k.keter is NULL
You sum up NULL in your query. And a Sum of NULL is NULL. You should just replace SUM(k.keter) with COUNT(k.keter)
See for a small example
To count NULLs, you can use:
SUM(k.keter IS NULL)
Or:
COUNT(*) - COUNT(k.keter)
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 following schema:
+--+------+-----+----+
|id|device|token|cash|
+--+------+-----+----+
column device is unique and token is not unique and null by default.
What i want to achieve is to set all duplicate token values to default (null) leaving only one with highest cash. If duplicates have same cash leave first one.
I have heard about cursor, but it seems that it can be done with usual query.
I have tried following SELECT only to see if im right about my thought how to achieve this, but it seems im wrong.
SELECT
*
FROM
db.table
WHERE
db.table.token NOT IN (SELECT
*
FROM
(
SELECT DISTINCT
MAX(db.table.balance)
FROM
db.table
GROUP BY db.table.balance) temp
)
For example:
This table after query
+-----+---------+--------+-------+
| id | device | token | cash|
+-----+---------+--------+-------+
| 1 | dev_1 | tkn_1 | 3 |
| 2 | dev_2 | tkn_1 | 10 |
| 3 | dev_3 | tkn_2 | 10 |
| 4 | dev_4 | tkn_2 | 14 |
| 5 | dev_5 | tkn_3 | 10 |
| 6 | dev_6 | null | 10 |
| 7 | dev_7 | null | 10 |
| 8 | dev_8 | tkn_4 | 11 |
| 8 | dev_8 | tkn_4 | 11 |
| 8 | dev_8 | tkn_5 | 11 |
+-----+---------+--------+-------+
should be:
+-----+---------+--------+-------+
| id | device | token | cash|
+-----+---------+--------+-------+
| 1 | dev_1 | null | 3 |
| 2 | dev_2 | tkn_1 | 10 |
| 3 | dev_3 | null | 10 |
| 4 | dev_4 | tkn_2 | 14 |
| 5 | dev_5 | tkn_3 | 10 |
| 6 | dev_6 | null | 10 |
| 7 | dev_7 | null | 10 |
| 8 | dev_8 | tkn_4 | 11 |
| 8 | dev_8 | null | 11 |
| 8 | dev_8 | tkn_5 | 15 |
+-----+---------+--------+-------+
Thanks in advance :)
Try using an EXISTS subquery:
UPDATE yourTable t1
SET token = NULL
WHERE EXISTS (SELECT 1 FROM (SELECT * FROM yourTable) t2
WHERE t2.token = t1.token AND
t2.cash > t1.cash);
Demo
Note that this answer assumes that there would never be a tie for two token records having the same highest cash amount.
To set exactly one row in the even of duplicates on the maximum cash, use the id:
update t join
(select tt.*,
(select t3.id
from t t3
where t3.token = tt.token
order by t3.cash desc, id desc
) as max_cash_id
from t tt
) tt
on t.id = tt.id and t.id < tt.max_cash_id
set token = null;
I have a search section for looking up products which has a navigation bar for filtering purposes that shows the total results of each product feature. For example:
TOTAL RESULTS 60
New (32)
Used (28)
Particular (10)
Company (50)
In mysql I have the following queries (one per feature)
Type
SELECT a.id_type, whois.name as whoisName, COUNT(a.id_type) as countWhois
FROM (published a
INNER JOIN types whois ON whois.id = a.id_type)
GROUP BY id_type
+---------+------------+------------+
| id_type | whoisName | countWhois |
+---------+------------+------------+
| 0 | Company | 50 |
| 1 | Particular | 10 |
+---------+------------+------------+
Condition
SELECT a.id_condition, cond.name as condName, COUNT(a.id_condition) as countCondition
FROM (published a
INNER JOIN conditions cond ON cond.id = a.id_condition)
GROUP BY id_condition
+--------------+---------------+----------------+
| id_condition | conditionName | countCondition |
+--------------+---------------+----------------+
| 0 | New | 32 |
| 1 | Used | 28 |
+--------------+---------------+----------------+
I want to summarize the two queries in a single one but canĀ“t figure out how. I was thinking something like this:
+---------+------------+------------+--------------+---------------+----------------+
| id_type | whoisName | countWhois | id_condition | conditionName | countCondition |
+---------+------------+------------+--------------+---------------+----------------+
| 0 | Company | 50 | NULL | NULL | NULL |
| 1 | Particular | 10 | NULL | NULL | NULL |
| NULL | NULL | NULL | 0 | New | 32 |
| NULL | NULL | NULL | 1 | Used | 28 |
+---------+------------+------------+--------------+---------------+----------------+
Is this possible?
Thanks and sorry if my English is bad, it's not my native language.
What I have until now: http://sqlfiddle.com/#!2/bbfec/6
I want to get the quanity of shares for a given stock, that a given company has available to sell - grouped by price. For example, for company number 9 and stock number 1, I want the data like this:
| id | name | price | date | quantity | total |
------------------------------------------------------------------
| 3 | ALTR | 2.240 | 2015-05-12 04:29:29 | 50 | 112.00 |
| 7 | ALTR | 2.449 | 2014-06-10 18:21:02 | 50 | 122.45 |
Because company 9 bought 200 stocks on 2015-05-12 04:29:29, sold 100 on 2014-06-10 15:50:17, more 50 on 2014-06-10 17:06:18 and bought 50 on 2014-06-10 18:21:02.
I don't want the total of all shares, because they have different prices when a company acquires them. The price and the date are the purchasing price and date but the quantity is what is left from a certain purchasing.
Thanks in advance.
Strawberry, the desired result:
| id | price | date | quantity |
-----------------------------------------------
| 3 | 2.240 | 12-05-2015 | 50 |
| 7 | 2.449 | 10-06-2014 | 50 |
Start with:
select id_acao, id_empresa, ifnull(bought,0) - ifnull(sold,0) as stock
from
(
select id_acao, id_empresa,
(select sum(quantidade) from acao_trans where tipo='C' and id_acao=a.id_acao and id_empresa=a.id_empresa) as bought,
(select sum(quantidade) from acao_trans where tipo='V' and id_acao=a.id_acao and id_empresa=a.id_empresa) as sold
from acao_trans a group by id_acao,id_empresa
) x
;
+---------+------------+-------+
| id_acao | id_empresa | stock |
+---------+------------+-------+
| 1 | 4 | 1500 |
| 1 | 9 | 100 |
| 8 | 9 | 3500 |
| 13 | 9 | 5000 |
+---------+------------+-------+
And join this query to your base acao and empresa tables.
Remark: For statistics etc. it would be easier to use negative quantities for selling transactions instead of a transaction type 'C' and 'V'.
For ease of (my) comprehension, I translated and adjusted your stock table slightly...
SELECT a.stock_id
, a.company_id
, a.transaction_date
, a.price
, COALESCE(a.quantity - SUM(b.quantity),a.quantity) quantity
, COALESCE(a.quantity - SUM(b.quantity),a.quantity) * a.price subtotal
FROM stock_company a
LEFT
JOIN
( SELECT x.stock_id
, x.company_id
, MAX(x.transaction_date) min_transaction_date
, y.quantity
FROM stock_company x
JOIN stock_company y
ON y.stock_id = x.stock_id
AND y.company_id = x.company_id
AND y.transaction_date <= x.transaction_date
AND y.transaction_type <> x.transaction_type
WHERE y.transaction_type = 'SELL'
GROUP
BY x.stock_id
, x.company_id
, y.quantity
) b
ON b.stock_id = a.stock_id
AND b.company_id = a.company_id
AND b.min_transaction_date = a.transaction_date
WHERE a.stock_id = 1
AND a.company_id = 9
AND a.transaction_type = 'BUY'
GROUP
BY stock_id
, company_id
, transaction_date;
+----------+------------+---------------------+-------+----------+----------+
| stock_id | company_id | transaction_date | price | quantity | subtotal |
+----------+------------+---------------------+-------+----------+----------+
| 1 | 9 | 2014-06-10 18:21:02 | 2.449 | 50 | 122.450 |
| 1 | 9 | 2015-05-12 04:29:29 | 2.240 | 50 | 112.000 |
+----------+------------+---------------------+-------+----------+----------+
http://www.sqlfiddle.com/#!2/cfa4d/1
Note that this hasn't been tested extensively so there may be a flaw (or perhaps several flaws!) in my logic, but it seems to work well enough on the data set provided.
EDIT: I made a slight adjustment - still not sure if it's enough. Let me know.
Maybe now I've understood it. How about this:
select c.id,c.id_empresa,c.id_acao,c.data as c_data,c.quantidade as c_quantidade,v.preco,v.id as v_id,v.data as v_data,ifnull(v.quantidade,0) as v_quantidade, c.preco*v.quantidade as bought, v.preco*v.quantidade as sold
from acao_trans c
left join acao_trans v
on c.id=v.parent
order by id_empresa, id_acao,c_data,v_data
which results in
+----+------------+---------+---------------------+--------------+-------+------+---------------------+--------------+----------+----------+
| id | id_empresa | id_acao | c_data | c_quantidade | preco | v_id | v_data | v_quantidade | bought | sold |
+----+------------+---------+---------------------+--------------+-------+------+---------------------+--------------+----------+----------+
| 4 | 4 | 1 | 2014-06-10 08:59:09 | 2000 | 2.385 | 8 | 2014-06-11 10:39:48 | 500 | 1184.000 | 1192.500 |
| 8 | 4 | 1 | 2014-06-11 10:39:48 | 500 | NULL | NULL | NULL | 0 | NULL | NULL |
| 5 | 9 | 1 | 2014-06-10 15:50:17 | 100 | NULL | NULL | NULL | 0 | NULL | NULL |
| 6 | 9 | 1 | 2014-06-10 17:06:18 | 50 | NULL | NULL | NULL | 0 | NULL | NULL |
| 7 | 9 | 1 | 2014-06-10 18:21:02 | 50 | NULL | NULL | NULL | 0 | NULL | NULL |
| 3 | 9 | 1 | 2015-05-12 04:29:29 | 200 | 2.430 | 5 | 2014-06-10 15:50:17 | 100 | 224.000 | 243.000 |
| 3 | 9 | 1 | 2015-05-12 04:29:29 | 200 | 2.449 | 6 | 2014-06-10 17:06:18 | 50 | 112.000 | 122.450 |
| 2 | 9 | 8 | 2015-05-12 04:27:56 | 3500 | NULL | NULL | NULL | 0 | NULL | NULL |
| 1 | 9 | 13 | 2015-05-12 04:25:52 | 5000 | NULL | NULL | NULL | 0 | NULL | NULL |
+----+------------+---------+---------------------+--------------+-------+------+---------------------+--------------+----------+----------+
Can you go on from there?
Ok, now I think I got it.
Here's the query resulting what I wanted:
SELECT p.id
, a.nome
, p.preco
, date_format(p.`data`,'%m/%d/%Y') AS `data`
, COALESCE(p.quantidade-SUM(f.quantidade), p.quantidade) AS quantidade
, p.preco*COALESCE(p.quantidade-SUM(f.quantidade), p.quantidade) AS total
FROM acao_trans p
LEFT JOIN acao_trans f
ON p.id=f.parent
INNER JOIN acao a
ON p.id_acao=a.id
WHERE p.parent IS NULL
AND p.id_acao=1
AND p.id_empresa=9
GROUP BY p.id
Fiddle: http://sqlfiddle.com/#!2/bbfec/64.
What I did: I joined the table that matters (acao_trans "p") with itself ("f") and I used Sum function to aggregate all the quantities of second argument, giving me the total of all sold shares. If there are records on "f" I want to subtract that total of the quantity of purchasing shares ("p"). If there is not a correspondence it will show null fields and I show purchased quantity. After it's done it's kind of simple. Quantity was what really mattered here, with that I was able to reach other things easily.