count result output don't show if result is zero - mysql

Count multiple column using the following query:
select count(price) as a ,count(buy_price) as b from table where c=1
if a or b one of result are zero then that column don't show. suppose count(price) as a output is 0 and count(buy_price) as b is 10 then output will be:
b
10

First and foremost, your query should look like this:
select count(price) as a, count(buy_price) as b from table where c=1
Note the comma (",") between ...as a and count(buy_price)....
In general, you should have commas separating the fields in your projection, e.g.:
select field1, field2, field3 from myTable
If you really want both fields to appear in your result set, you'll need to use the built-in IFNULL function:
select COUNT(IF(price=0,1,price)) as a, COUNT(IF(buy_price=0,1,buy_price)) as b from table where c=1

Related

Converting multivalued column in table A to multiple rows in table B Mysql

Given 2 tables, I want to convert the multivalued row in table 1
Given 2 tables
Table A
id value
ae [1,2,4,5]
ac [1,6]
Table B
id value
ae 1
ae 2
ae 4
ae 5
ac 1
ac 6
I know I have to insert a before insert trigger on table B, but I cannot figure out the logic.
Another way to convert JSON arrays in MySQL into rows (I assume "value" column in table A is json array type). Transform Table A into Table B.
MySql >= 8.0:
First with a recursive query I get json array indexes for each json array with a length > 0 (a row per index), then I join table A with indexes query and used JSON_EXTRACT() to extract each json array value in a row.
WITH RECURSIVE indexes AS (SELECT id, 0 AS json_index FROM A WHERE JSON_LENGTH(value) > 0
UNION ALL
SELECT i.id, i.json_index + 1
FROM indexes i
INNER JOIN A ON A.id = i.id AND i.json_index < JSON_LENGTH(A.value) - 1
)
SELECT A.id, JSON_EXTRACT(A.value, CONCAT('$[', i.json_index, ']')) AS arrayValue
FROM A
INNER JOIN indexes i ON A.id = i.id;
Here's an idea:
Get the total of value need to be separated using LENGTH():
Take the first example [1,2,4,5]. There are 4 values separated by commas here. If we do LENGTH(value), we will get 9 as there are 9 characters including [ and ,. Then we do LENGTH(REPLACE(value,',','')) which we replace the commas from the values with nothing and this will give us 6. If we subtract them, we'll get 3 which we suppose to get 4 so we add +1 in the final calculation. We end up with something like this:
(LENGTH(value)-LENGTH(REPLACE(value, ',', '' )))+1
With that, you'll get ae with 4 and ac with 2. From here there are three usage of this information:
To make a numbering sequence referring to the largest number we get, in this case 4.
To return repeated row based on how many length the value column has.
To be used in SUBSTRING_INDEX() function and return the value accordingly.
In the end, I've managed to create two queries using the same idea but for a different MySQL version.
For older MySQL version (before v8), this might do:
SELECT id,
SUBSTRING_INDEX(SUBSTRING_INDEX(val,',',ln),',',-1) AS value
FROM
(SELECT 1 AS ln UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) RN
LEFT JOIN
(SELECT id,
REPLACE(REPLACE(value,'[',''),']','') AS val
FROM tableA) A
ON ln<=(LENGTH(val)-LENGTH(REPLACE(val,',','')))+1
ORDER BY id, value;
However, the issue here is that the hardcoded numbering sequence by rows on this part of the query ..(SELECT 1 AS ln UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) RN... Meaning that if there's a value where the length is everchanging, then this part need to be constantly edited.
For MySQL v8 (but not quite v8.0.4 that supports JSON_TABLE):
WITH RECURSIVE cte AS (
SELECT 1 AS ln, MAX((length(value)-length(replace(value,',','')))+1) AS totval
from tableA UNION ALL
SELECT ln+1, totval FROM cte WHERE ln+1 <= totval)
SELECT id,
REGEXP_REPLACE(SUBSTRING_INDEX(SUBSTRING_INDEX(value,',',ln),',',-1),'[^0-9]','') AS value
FROM cte
LEFT JOIN tableA
ON ln<=(length(value)-length(replace(value,',','')))+1
ORDER BY id, value;
Here I'm using WITH RECURSIVE function to dynamically generate the numbering sequence, which means that if the length is more than 4, there's no need to edit the query.
Demo fiddle

MySQL conditional concatenate based on multiple columns

I'm stumped on a proper query to get an output based on multiple columns and the conditions in those columns:
a b c
1 x x
2 x x
3 x
I would like the results to output, based on where the x's are in columns a, b and c:
1 a,c
2 a,b
3 a
Is this possible to do in mysql? Much appreciated
You can use the CONCAT_WS function (docs) and some IF statements.
SELECT tn.ID,
CONCAT_WS(
',',
IF(tn.a='x','a',null),
IF(tn.b='x','b',null),
IF(tn.c='x','c',null)
) as result
FROM TableName tn;
You can use IFNULL function for that (docs). For example:
SELECT a, IFNULL(b, c) FROM table_name;
It will select a for every case and conditionally b or c, depending on it's value (it have to be not null). But I'm afraid you cannot do more than that.

Sort columns based on data in tuples mysql

Say, I have a table
A B C D E F
1 2 4 3 6 5
4 2 3 1 6 5
4 5 3 6 1 2
How can one get an output based on rearranging based on its data. For example,
ABDCFE
DBCAFE
EFCABD
is it possible?
EDIT:
The question seems to be asking: How can I get the list of column names in order by value?
I got it. You want to sort the values in each row and show the names of the columns in order.
Let me assume that you have a row id, so you can identify each row. Then:
select id, group_concat(which order by val) as ordered_column_names
from ((select id, a as val, 'A' as which from t) union all
(select id, b, 'B' as which from t) union all
(select id, c, 'C' as which from t) union all
(select id, d, 'D' as which from t) union all
(select id, e, 'E' as which from t) union all
(select id, f, 'F' as which from t)
) t
group by id
order by id;
SQL is fundamentally not the tool to do the operation you describe, because it violates the concept of a relation. I don't mean the common use of "relation" meaning a relationship, I mean the mathematical definition of relation.
There is no order of columns in a relation. The columns are a set, which is by definition unordered. Columns are identified by their name, not their position left-to-right.
All the entries in rows under each respective named column must be part of the same data domain. If you mix them around on a row-by-row basis, you're violating this.
I guess all your columns A through F are actually using values in the same data domain, or else reordering them wouldn't make any sense. If this is true, then you're violating First Normal Form by defining a table with repeating groups of columns. You should instead have all six columns be in one column of a second table. Then it becomes very easy to sort them by value.
Basically, what you're trying to do is better solved by formatting the data results in some application code.
There is a way to do it ,get coulmn name by column ordinal order and print it.
For each value in coulmn iterate this and get the column name for the ordinal specified in cloumn data. Here ordinal position is value in each coulmn data. Iterate for each row and each column and your problem is solved.
select column_name
from information_schema.columns
where table_name = 'my_table_name' and ordinal_position = 2;
It appears that you are asking for output where each row in the output is just a specification of the order of the data values in the columns.
Then, if the values are always integers between 1 and 5, you can do it by outputting a character value of 'A' where the data value is 1, a 'B' where the data value is 2, etc. This SQL will do that.
Select Char(A+64)A, Char(B+64) B,
Char(C+64) C, Char(D+64) D,
Char(E+64) E, Char(F+64) F
From table
if the want the column sort order in one output column, you could also do this:
Select Char(A+64) + Char(B+64) +
Char(C+64) + Char(D+64) +
Char(E+64) + Char(F+64) SortOrder
From table

Show column value twice in MySql Select

If I have a MySql table with values
col1
=====
1
1
1
5
5
5
5
7
7
I want to get all distinct values of col1 (i.e. 1,5,) and get output with one SELECT statement as follows:
1~1
5~5
7~7
How can I do this?
Here's the query:
Use separator ~ in GROUP_CONCAT function.
Query #1 use case scenario: If you want to separate the col1 values by tide (~) only if the corresponding value has identical values across the table.
Query #1:
SELECT
GROUP_CONCAT(col1 SEPARATOR '~') output
FROM scotttable
GROUP BY col1;
SQL FIDDLE DEMO
Note: It will work for any number of identical values.
Query #2 use case scenario: Only if you want the distinct col1 values no matter if they have corresponding identical value across the table exists or not.
Query #2:
SELECT
CONCAT(col1,'~',col1) output
FROM scotttable
GROUP BY col1;
FIDDLE OF THIS QUERY
Here is an option using a subquery:
SELECT CONCAT(t.value, '~', t.value)
FROM
(
SELECT DISTINCT col1 AS value
FROM yourTable
) t
Follow the link below for a running demo:
SQLFiddle

mysql select with 2 different substrings and single WHERE from 1 column

i am trying to pull data from sql with several conditions from a single column
how can i get this to work?
SELECT RIGHT(productID, 2) AS 'a', SUBSTRING(productID,1,2) AS 'b', productID
FROM products
WHERE `group`='$one'
AND `a` LIKE 'AA%'
AND `b` LIKE '$two'
i am trying to get the first 2 letters of the row and last 2 letters from the same row as well as checking if group=$one but get this error
Unknown column 'b' in 'where clause'
SELECT RIGHT(productID, 2) AS 'a', SUBSTRING(productID,1,2) AS 'b', productID
FROM products
WHERE `group`='$one'
GROUP BY productID
HAVING
a = 'AA'
and b LIKE '$two'
No need for the like it's two positions % increases execution.
I created a simple table (sotest for StackOverFlow Test table) and added a VARCHAR column to it called col1. The code below worked for me.
SELECT RIGHT(col1, 2) AS a, SUBSTRING(col1,1,2) AS b, col1 as col FROM sotest Having a like 'in%' and b like 'te%'
The return is as bellow
| a | b | col |
|'in'| 'te'| 'test_jermin'|
SELECT RIGHT(productID), 2)
^---extra bracket
you're terminating the function before you specify how many characters to extract.
That is because of your error in RIGHT function call, you have a misplaced parenthesis. Change the statement of SELECT to this:
SELECT RIGHT(productID, 2)