Counting the ratio mysql - mysql

Say I have the following table,
I would like to select the ratio of all the names that start with A to all the names that start with B
For example
Name
ABC
DEF
VVV
BBB
BCD
ZZZ
So the output would be 0.5. I want to call that output 'out'.
So the output should be
out
0.5
pretty much what I want is
Select count(*) from table where name like 'A%' / select count(*) from table where name like 'B%'
but in a single query.

You can do something like:
select
(select count(*) from table where name like 'a%') / (select count(*) from table where name like 'b%');
Here's a SQL Fiddle.
Note that if the divisor is zero, mySql will coalesce the zero into a null and the resulting value will be null. This is different than say, Oracle, which will throw a divisor is equal to zero exception.
Here's a SQL Fiddle showing this behavior, which you should probably trap and handle appropriately.

This query will do what you need:
SELECT ((SELECT COUNT(*) FROM `table` WHERE name LIKE 'A%') /
(SELECT COUNT(*) FROM `table` WHERE name LIKE 'B%')) AS `out`

Related

WHERE x IN works with a single value, not with multiple on json

There's a hard to understand issue with querying on a json field in MySQL. The data column is of type json.
The following query works perfectly fine
SELECT * FROM `someTable` WHERE data->'$.someData' in ('A')
However the following one returns nothing.
SELECT * FROM `someTable` WHERE data->'$.someData' in ('A','B')
Funnily enough this also works:
SELECT * FROM `someTable` WHERE data->'$.someData'='A' OR data->'$.someData'='B'
I'm clueless as to why this happens. I originally thought that WHERE x IN executed in a json query format might be doing something like && but even if the values are ('A','A') it still returns nothing which essentially shows that more than one value in WHERE x IN wont work.
SAMPLE DATA (any would do really)
id | data (json)
1 | {"someData":"A"}
2 | {"someData":"B"}
Too long for a comment...
This seems to be related to an optimisation MySQL is performing when there is only one value in the IN expression (probably converting it to an a = b expression) and then it ignoring quotes. Strictly speaking,
SELECT *
FROM `someTable`
WHERE data->'$.someData' in ('A')
or
SELECT *
FROM `someTable`
WHERE data->'$.someData' = 'A'
should return no data because
SELECT data->'$.someData'
FROM someTable;
returns
"A"
"B"
which is not the same as A. You need to use JSON_UNQUOTE (or if you have MySQL 5.7.13 or later the ->> operator) to get the actual value of the someData key:
SELECT JSON_UNQUOTE(data->'$.someData') FROm someTable;
SELECT data->>'$.someData' FROm someTable;
which gives
A
B
which then works fine with an IN expression:
SELECT *
FROM `someTable`
WHERE JSON_UNQUOTE(data->'$.someData') in ('A','B')
-- or use WHERE data->>'$.someData' in ('A','B')
Output:
id data
1 {"someData":"A"}
2 {"someData":"B"}
Demo on dbfiddle
You could try using a join on a subquery instead of a IN clause
SELECT *
FROM `someTable` s
INNER JOIN (
select 'A' col
union
select 'B'
) t ON t.col = s.data->'$.someData

How to use DISTINCT command in SQL

Below shows my data table name called "company"
Here is my SQL query
SELECT
name, COUNT(DISTINCT num) AS count
FROM
company
WHERE
(num LIKE '51%' OR num LIKE '65%' OR num LIKE '81%')
GROUP BY
name
After run this query it shows below result
But I need below result. Please help me to solve my problem. Thank you
I assume you want to have the distinct on the first 2 characters of the column.
You can use the function LEFT() for this:
Query
SELECT name , COUNT(DISTINCT LEFT(num, 2)) AS count
FROM new_table
WHERE ( num LIKE '51%' OR num LIKE '65%' OR num LIKE '81%')
GROUP BY name

Multiple like condition in mysql

When i use multiple like condition with AND keyword, it will return false value actually, it had value in table and my query as below:
SELECT * FROM tbl_student
WHERE name LIKE '%jame%'
AND ( id LIKE '%001%'
AND id2 LIKE '%002%'
)
This query return empty row
SELECT * FROM tbl_student
WHERE name LIKE '%jame%'
OR ( id LIKE '%001%'
AND id2 LIKE '%002%'
)
This query return data
tbl_student
Name ID ID2
jame 233 3234
jame333 1001 0222
jame333 Da 1001 1002
Why it is returned empty data when use AND keyword ?
Your query with the AND operator does not return the desired data, because your conditions placed within brackets always evaluate to false.
The reason this occurs is because you are trying to use LIKE '%str%' on an integer. This will not work expectedly. If you insist on using LIKE, you might want to CAST your integers to strings:
SELECT *
FROM tbl_student
WHERE name LIKE '%jame%'
AND (CAST(id AS CHAR) LIKE '%001%' AND
CAST(id2 AS CHAR) LIKE '%002%');
FYI, an e1 AND (e2 AND e3) logical expression remains the same with the brackets omitted.

subquery or passthrough; SQL Server 2008r2

I have an Access 2000 query that works on linked tables from SQL Server 2008 R2. I need to write it as a view or pass through query:
`
SELECT Max(CLng((Mid([tbl1]![ID],5)))) AS lastnumberused
FROM [tbl1]
WHERE ((([tbl1]![ID]) Like "OODD*" And ([tbl1]![ID]) Not Like "OODDid*" And ([tbl1]![ID]) Not Like "*x") AND ((CLng((Mid([tbl1]![ID],5))))<1000000));
`
So what I'm looking for is the max number under 1000000 that begins with OODD% but not OODDID%. Also the record cannot end with 'x'.
My code in TSQL for SQL Server looks like this and doesn't work...
`
SELECT
convert (int, (substring(tblMain.BarcodeID,5,10))) as X1, [ID]
FROM tblMain
WHERE ([tbl1]![ID] LIKE N'OODD%')
AND ([tbl1]![ID] NOT LIKE N'%x%')
AND ([tbl1]![ID] NOT LIKE N'OODDID%')
Select MAX (x1)+1
from bar1
where (x1<1000000)
`
suggestions?
thanks,H
Update 15june2013
WITH T1 (number)
AS
(SELECT substring(tbl1.ID,5,10)
FROM tblMain AS tbl1
WHERE (ID LIKE N'oodd%')
AND (ID NOT LIKE N'%x%')
AND (ID NOT LIKE N'ooddID%'))
SELECT (cast((number)as int)) FROM T1
This works and returns 561770 rows.
With T1(number)
as(SELECT cast(SUBSTRING(ID, 5, 7)as int)
FROM tblMain as tbl1
WHERE (tbl1.ID LIKE N'oodd%')
AND (tbl1.ID NOT LIKE N'%x%')
AND (tbl1.ID NOT LIKE N'%ooddID%')
AND ISNUMERIC(SUBSTRING(tbl1.ID,5,10))=1)
Select max(number) from T1
Also works but returns a number above 1000000
When a where statement is added the following code includes records that should have been excluded in the previous statement.
With T1(number)
as(SELECT cast(SUBSTRING(ID, 5, 7)as int)
FROM tblMain as tbl1
WHERE (tbl1.ID LIKE N'oodd%')
AND (tbl1.ID NOT LIKE N'%x%')
AND (tbl1.ID NOT LIKE N'%ooddID%')
AND ISNUMERIC(SUBSTRING(tbl1.ID,5,10))=1)
Select max(number) from T1
where x1 <1000000
The WHERE clause contains a [tbl1] table which is not present in the FROM clause. You should either change it to tblMainBee or add an "tbl1" alias in the FROM clause with AS.
Also, you have two unconnected SELECT statements, instead of a single one. Again, in the second SELECT, there is a bar1 table which doesn't appear anywhere else... is it correct?
Another error is that you cannot use "!" to separate table name and field name. You must use a dot.
Finally, there are issues when trying to convert the data type. You don't need it since comparison between strings also works.
Your access SELECT statement is much more straightforward.
Try with
WITH T1(number) AS (
SELECT substring(tbl1.ID,5,LEN(tbl1.ID)-4)
FROM tblMainBee as tbl1
WHERE ([tbl1].[ID] LIKE N'OODD%')
AND ([tbl1].[ID] NOT LIKE N'%x%')
AND ([tbl1].[ID] NOT LIKE N'OODDID%')
AND (IsNumeric(substring(tbl1.ID,5,LEN(tbl1.ID)-4)) = 1)
)
SELECT max(convert(bigint,number)) FROM T1 WHERE number < 1000000;
The second type conversion is implicit since 1000000 is numeric. The first one is necessary. Otherwise, it would consider '12346' bigger than '123421'.
Comparison between strings only works if they have fixed length.
Regards,
Try this
select MAX(CAST(SUBSTRING(ID,5,9) as INT))+1
from tblMainBee
where
ID Like 'OODD%'
AND ID Not Like 'OODDid%'
AND ID Not Like '%x'
AND ISNUMERIC(SUBSTRING(ID,5,9))=1
AND CAST(SUBSTRING(ID,5,9) as INT)<1000000

How to get the max value of a field without grouping in MySql

I have a query with many wheres and orders criterias. One of the fields of the select is 'price' (element price) but I would like to have also (in every row) the maximun price of all the selected elements.
I tried to include MAX aggregate function on select hoping that this will return desired value, but insetead of that, price and MAX(price) returns the same. Searching into MySql doc I found the reason:
If you use a group function in a
statement containing no GROUP BY
clause, it is equivalent to grouping
on all rows.
Is there a way to solve this problem?
Thanks in advance!
There's a similar question (but not resolving this): find max value without aggregate operator in mysql
You can do this:
SELECT
id,
price,
(SELECT MAX(price) FROM your_table) AS max_price
FROM your_table
I'm not sure why you'd want to return that value on every row though... I'd probably do this in two separate queries, or else use a UNION ALL:
SELECT id, price FROM your_table
UNION ALL
SELECT NULL, MAX(price) FROM your_table
Maybe you could use a stored procedure like so:
CREATE PROCEDURE QueryWithMax ([parameter list if necessary])
BEGIN
-- Obtain the maximum price
DECLARE x INT UNSIGNED; -- change datatype if appropriate
SET x = SELECT
MAX(price)
FROM
...
WHERE
...
;
-- Now do your query
SELECT
price,
[other columns],
x AS MaxPrice
FROM
...
WHERE
...
GROUP BY
...
;
END
I haven't tried this, but if you had a subquery that extracts the maximum price (so you get one row), and then do a cross join (cartesian product) with it. You should get something like what you want. I can't vouch for how fast this would be.