Mysql clear code in one line - mysql

i was searching on google and in stackoverflow.com how can i write this code clearly and nice but found nothing.
Any idea?
MySQL query:
SELECT COUNT(*) AS `allInvoice`,
(SELECT COUNT(*) FROM `ocr_entity` WHERE `status` = 0) AS `new`,
(SELECT COUNT(*) FROM `ocr_entity` WHERE `status` = 10) AS `notTemplate`,
(SELECT COUNT(*) FROM `ocr_entity` WHERE `status` = 50) AS `withMistake`,
(SELECT COUNT(*) FROM `ocr_entity` WHERE `status` = 100) AS `finished`,
(SELECT COUNT(*) FROM `ocr_entity` WHERE `status` = 200) AS `skipped`
FROM `ocr_entity`;

Use conditional aggregation:
SELECT COUNT(*) AS `allInvoice`,
SUM( `status` = 0 ) AS `new`,
SUM( `status` = 10 ) AS `notTemplate`,
SUM( `status` = 50 ) AS `withMistake`,
SUM( `status` = 100 ) AS `finished`,
SUM( `status` = 200 ) AS `skipped`
FROM `ocr_entity`;
MySQL treats booleans as numbers in a numeric context, with 0 for false and 1 for true (which is why SUM() works).

Related

Count Total from Multiple Table

I have 3 tables (ticket1, ticket2, ticket3) that contain same field:
ticket1: ticket2: ticket2:
======== ======== ========
ticket_id ticket_id ticket_id
status status status
And my query just like this:
("SELECT (SELECT COUNT( * ) FROM `ticket1` WHERE `status` =9) AS done,
(SELECT COUNT( * ) FROM `ticket1` WHERE `status` =10) AS Incomplete,
(SELECT COUNT( * ) FROM `ticket1` WHERE `status` =2) AS New")
This is to count ticket and filter by status.
And my question is, how i can count all ticket into total Done, Incomplete, and New from ticket1, ticket2, ticket3.
Help me guys, thanks..
I guess the 3d table's name is ticket3, right?
SELECT
(SELECT COUNT(*) FROM `ticket1` WHERE `status` = 9) +
(SELECT COUNT(*) FROM `ticket2` WHERE `status` = 9) +
(SELECT COUNT(*) FROM `ticket3` WHERE `status` = 9) AS TotalDone,
(SELECT COUNT(*) FROM `ticket1` WHERE `status` = 10) +
(SELECT COUNT(*) FROM `ticket2` WHERE `status` = 10) +
(SELECT COUNT(*) FROM `ticket3` WHERE `status` = 10) AS TotalIncomplete,
(SELECT COUNT(*) FROM `ticket1` WHERE `status` = 2) +
(SELECT COUNT(*) FROM `ticket2` WHERE `status` = 2) +
(SELECT COUNT(*) FROM `ticket3` WHERE `status` = 2) AS TotalNew
Try this.
select status, count(1) from
(select * from ticket1
union all
select * from ticket2
union all
select * from ticket3) group by status;
Let me know if you face any issues
you could select from union all
select sum(case when status = 9 then 1 else 0 end) done,
sum(case when status = 10 then 1 else 0 end) Incomplete,
sum(case when status = 2 then 1 else 0 end) New,
sum(case when status in (9,10,2) then 1 else 0 end) deon_incomplete_new,
count(*) tot
from (
select ticket_id, status from ticket1
union all
select ticket_id, status from ticket2
union all
select ticket_id, status from ticket2
) t
I would suggest:
select sum(case when status = 9 then cnt else 0 end) as done,
sum(case when status = 10 then cnt else 0 end) as incomplete,
sum(case when status = 2 then cnt else 0 end) as new
from ((select status, count(*) as cnt from ticket1 group by status
) union all
(select status, count(*) as cnt from ticket2 group by status
) union all
(select status, count(*) as cnt from ticket3 group by status
)
) t;
Or, you might consider putting the values in separate rows using group by.
If performance is an issue and you have lots of other tickets statuses (or more specifically lots of rows with different statuses), then where status in (2, 9, 10) in each of the subqueries might help.

2 SQL queries at once

How can I concatenate these two queries, so that I can have 3 columns in my result: postcode, memberCount and placeCount
SELECT LEFT(`delivery_postcode`, 2) as `postcode`, count(`delivery_postcode`) as `count`
FROM `customer_cards`
WHERE `delivery_postcode` IS NOT NULL
AND `delivery_postcode` <> ''
GROUP BY `postcode`
ORDER BY `count` DESC
and
SELECT LEFT(`placePostcode`, 2) as `postcode`, count(`placePostcode`) as `placeCount`
FROM `RestaurantsForGoogleMaps`
WHERE `placePostcode` IS NOT NULL
AND `placePostcode` <> ''
GROUP BY `postcode`
ORDER BY `placeCount` DESC
At the moment my results look like the following, for either query
postcode | count/placeCount
------------------------
SW | 817
W1 | 533
EC | 395
Something like this should work:
SELECT LEFT(`delivery_postcode`, 2) as `postcode`
, count(`delivery_postcode`) as `count`
, pc.placeCount
FROM `customer_cards` cc
LEFT JOIN (
SELECT LEFT(`placePostcode`, 2) as `postcode`,
count(`placePostcode`) as `placeCount`
FROM `RestaurantsForGoogleMaps`
WHERE `placePostcode` IS NOT NULL
AND `placePostcode` <> ''
GROUP BY `postcode`
) pc
on pc.postcode = LEFT(cc.delivery_postcode, 2)
WHERE `delivery_postcode` IS NOT NULL
AND `delivery_postcode` <> ''
GROUP BY `postcode`
ORDER BY `count` DESC
SELECT postcode,count,placecount FROM (SELECT LEFT(`delivery_postcode`, 2) as `postcode`, count(`delivery_postcode`) as `count`, 0 as `placecount`
FROM `customer_cards`
WHERE `delivery_postcode` IS NOT NULL
AND `delivery_postcode` <> ''
GROUP BY `postcode`
UNION
SELECT LEFT(`placePostcode`, 2) as `postcode`, count(`placePostcode`) as `placecount`,0 as `count`
FROM `RestaurantsForGoogleMaps`
WHERE `placePostcode` IS NOT NULL
AND `placePostcode` <> ''
GROUP BY `postcode` ) ORDER BY count desc
At the moment my results look like the following, for either query
;WITH PC1 AS (
SELECT LEFT(`delivery_postcode`, 2) as `postcode`, count(`delivery_postcode`) as `count`
FROM `customer_cards`
WHERE `delivery_postcode` IS NOT NULL
AND `delivery_postcode` <> ''
GROUP BY `postcode`
ORDER BY `count` DESC
),
PC2 AS (
SELECT LEFT(`placePostcode`, 2) as `postcode`, count(`placePostcode`) as `placeCount`
FROM `RestaurantsForGoogleMaps`
WHERE `placePostcode` IS NOT NULL
AND `placePostcode` <> ''
GROUP BY `postcode`
ORDER BY `placeCount` DESC
)
SELECT a.postcode, a.count,b.placeCount
FROM PC1 a
LEFT JOIN PC2 b
ON a.postcode = b.postcode
Create both queries as an inline views and then join on postcode. This assumes both queries return the desired results and that POST CODE is the key on which to join and there are no other attributes needing to complete the join properly. It also assumes the post code would be in both tables.
If not, then we have to replicate the join as right and left and union the results together.
SELECT A.postcode, A.mcount, B.placecount
FROM
(SELECT LEFT(delivery_postcode, 2) as postcode, count(delivery_postcode) as mcount
FROM customer_cards
WHERE delivery_postcode IS NOT NULL
AND delivery_postcode <> ''
GROUP BY LEFT(delivery_postcode, 2)) A
INNER JOIN (
SELECT LEFT(placePostcode, 2) as postcode, count(placePostcode) as placeCount
FROM RestaurantsForGoogleMaps
WHERE placePostcode IS NOT NULL
AND placePostcode <> ''
GROUP BY LEFT(placePostcode, 2)) B
on A.postcode = B.postcode
order by A.postcode

Two select statements

SELECT COUNT( DISTINCT `student_id` )
FROM a
WHERE `marks` >=90
The above gives me count of student with marks greater than 90,
COUNT( DISTINCT `student_id` )
4
Now I want two answers, one with marks > 90 and another >80
Something like this
COUNT( DISTINCT `student_id` ) |COUNT( DISTINCT `student_id` )
4 5
This is what I have tried after google search
select
count_1 =( SELECT COUNT( DISTINCT `student_id` )
FROM a
WHERE `marks` >=90),
count_2 =( SELECT COUNT( DISTINCT `student_id` )
FROM a
WHERE `marks` >=80)
I think the simpliest answer would be by using implicit boolean condition since MySQL supports it,
SELECT SUM(marks >= 90) Count_1,
SUM(marks >= 80) Count_1
FROM a
WHERE marks >= 80
The WHERE clause makes the searching more faster since it will filter the records first than running through all records.
You can use a CASE expression with an aggregate function:
SELECT
sum(case when `marks` >= 90 then 1 else 0 end) count_1,
sum(case when `marks` >= 80 then 1 else 0 end) count_2
FROM a
Then if you have more counts to get you will add more case expressions.
Or you can use:
SELECT
count(distinct case when `marks` >= 90 then `student_id` end) count_1,
count(distinct case when `marks` >= 80 then `student_id` end) count_2
FROM a

MySQL - Want to Minus two SUM() values from two SELECT statements

I want to be able to grab the two values that I have generated in SUM() from two SELECT queries and minus these values in order to get the result (OutstandingFunds).
These are my two SELECT queries:
Statement (1):
SELECT SUM(Cf.Amount) AS ClearedFunds
FROM (
SELECT Amount FROM PAYMENT1 WHERE `Status` = "Cleared"
UNION ALL
SELECT Amount FROM PAYMENT2 WHERE `Status` = "Cleared"
UNION ALL
SELECT Amount FROM PAYMENT3 WHERE `Status` = "Cleared") AS Cf;
Statement (2):
SELECT SUM(Price) AS TotalSales
FROM PROPERTY
WHERE Status = “Sold”;
Thank you for your time
If you don't need to show the separate subtotal for total sales and cleared funds, you can do it like this:
SELECT SUM(Total.`Price`) AS ClearedFunds
FROM (
SELECT `Price` FROM PROPERTY WHERE `Status` = 'Sold'
UNION ALL
SELECT (`Amount` * -1) AS `Price` FROM PAYMENT1 WHERE `Status` = 'Cleared'
UNION ALL
SELECT (`Amount` * -1) AS `Price` FROM PAYMENT2 WHERE `Status` = 'Cleared'
UNION ALL
SELECT (`Amount` * -1) AS `Price` FROM PAYMENT3 WHERE `Status` = 'Cleared'
) AS Total;
I am assuming you are wanting to subtract cleared funds from total sales here.
You were almost there... here's the working SQL:
SELECT (SELECT SUM(Cf.Amount) AS ClearedFunds
FROM (
SELECT Amount FROM PAYMENT1 WHERE `Status` = "Cleared"
UNION ALL
SELECT Amount FROM PAYMENT2 WHERE `Status` = "Cleared"
UNION ALL
SELECT Amount FROM PAYMENT3 WHERE `Status` = "Cleared") as Cf)
- (SELECT SUM(Price) AS TotalSales
FROM PROPERTY
WHERE Status = "Sold") as Result;
Here's the SQL Fiddle so that you can play with test data: http://sqlfiddle.com/#!2/18677/11
You can use SELECT ... INTO ..., in your case:
SELECT SUM(Cf.Amount) AS ClearedFunds
FROM (
SELECT Amount FROM PAYMENT1 WHERE `Status` = "Cleared"
UNION ALL
SELECT Amount FROM PAYMENT2 WHERE `Status` = "Cleared"
UNION ALL
SELECT Amount FROM PAYMENT3 WHERE `Status` = "Cleared") INTO #cf;
SELECT SUM(Price) AS TotalSales
FROM PROPERTY
WHERE Status = “Sold” INTO #ts;
Then you can substract or use them in any other query, like this:
SELECT #ts - #cf;
Are you looking for this?
SELECT C.ClearedFunds - P.TotalSales
FROM (
SELECT SUM(Cf.Amount) AS ClearedFunds
FROM (
SELECT Amount FROM PAYMENT1 WHERE `Status` = "Cleared"
UNION ALL
SELECT Amount FROM PAYMENT2 WHERE `Status` = "Cleared"
UNION ALL
SELECT Amount FROM PAYMENT3 WHERE `Status` = "Cleared") AS Cf) C,
(SELECT SUM(Price) AS TotalSales
FROM PROPERTY
WHERE Status = “Sold”) P
;

How do I combine these two Select queries with an OR case

I want to select all rows where WHERE (uid = {$uid} OR uid = **HERE** ) where **HERE** is the cids retreived from query 2 below.
Query 1:
SELECT * FROM `t_activities`
WHERE (`uid` = {$uid} OR `uid` = **HERE** )
AND `del` = 0
GROUP BY `fid`
ORDER BY `time` DESC
LIMIT 10
And Query 2:
SELECT `cid` FROM `t_con` WHERE `uid` = {$uid} AND `flag` = 1
SELECT * FROM `t_activities`
WHERE (`uid` = {$uid} OR `uid` in (SELECT `cid`
FROM `t_con`
WHERE `uid` = {$uid} AND `flag` = 1))
AND `del` = 0
GROUP BY `fid`
ORDER BY `time` DESC
LIMIT 10
You can do this as a join as well:
SELECT *
FROM `t_activities` ta left outer join
(SELECT `cid`
FROM `t_con`
WHERE `uid` = {$uid} AND `flag` = 1)
) tc
on ta = tc.cid
WHERE (`uid` = {$uid} OR tc.`uid` is not null) AND `del` = 0
GROUP BY `fid`
ORDER BY `time` DESC
LIMIT 10
By the way, as a SQL statement the "GROUP BY fid" looks very strange. This is allowed in mysql, but I think it is a bad practice. It is much better to be explicit about what you are doing:
SELECT fid, min(<field1>) as Field1, . . .
This helps prevent mistakes when you go back to the query or try to modify it.