MySQL Query to replace string with value - mysql

I have requirement like as below.
Need a MYSQL query to replace value with maching the below condition.
i have a table containg the Product ID
Product_ID
1
2
3
4
5
15
25
I want to replace the 5 with value of 1.111. My requiremnet is this that it should only replace the 5 value not the 15 value.
example 5 should be 1.111 but it sould not replace the 15 value.

You can use IF() or CASE to select a different value when the value meets a condition.
SELECT IF(product_id = '5', '1.111', product_id)
FROM yourTable
or
SELECT CASE product_id
WHEN '5' THEN '1.111'
ELSE product_id
END
FROM yourTable
CASE generalizes more easily to other values that you want to replace, since you can have multiple WHEN clauses.

Related

SQL - how to add a value with a condition to a selection?

I have the following table structure:
name
value
success
name 1
10
0
name 2
20
0
name 2
30
1
And my query is:
SELECT name, SUM(value) as valueTotal FROM TableName GROUP BY name
The result is:
name
valueTotal
name 1
10
name 2
50
Now I want to add a new column which will contain the sum of only successful rows. But if I add this condition, it will apply to all selected fields:
SELECT name, SUM(value) as valueTotal, SUM(value) as successValueTotal FROM TableName WHERE success = 1 GROUP BY name
Here is the result I want to get:
name
valueTotal
successValueTotal
name 1
10
0
name 2
50
30
How can I add a field with a separate condition that does not affect the main query? Thx)
You can use the SUM function with a conditional aggregation on whether success is 1 or not. When success is 1, then take the value of the value field, otherwise sum up 0.
SELECT name,
SUM(value) AS valueTotal,
SUM(IF(success = 1, value, 0)) AS successValueTotal
FROM TableName
GROUP BY name
Try it here.
This is the typical use case for CASE WHEN:
SELECT name,
SUM(value) AS valueTotal,
SUM(CASE WHEN success = 1 THEN value ELSE 0 END) AS successValueTotal
FROM TableName
GROUP BY name
You can (like lemon showed) also use an if clause in MYSQL. This is a bit shorter, but the query will not work on every DB while CASE WHEN does. So I think both is fine.

MySQL: Count rows with similar not duplicated content as one

I am working with Codeigniter and its Query Builder class where I have a table with IDs and names.
Those names look like 1234_1a or 2345_2a where 1a can be 1b or 2a,2b,3a... and so on.
Now I want to count all these "1234" and "2345" but write them as one type.
So far I tried with:
$this->db->like('names', '1a', 'before');
$this->db->or_like('names', '1b', 'before');
return $this->db->count_all_results('table');
But the problem:
What if there is 3456_2a but no 3456_1a, than it doesn't work anymore...
id name
2 1212_1a
3 1243_1a
7 3142_1a
24 1243_2a
30 3142_2b
80 2315_2b
136 1243_3b
512 8562_1a
This is how I would like it:
Result:
name count
1212 1
1243 1
3142 1
2315 1
8562 1
If we always want to return a count value of 1, when the count of the number of rows in more than 1 ... then we aren't really returning a count.
And what is the pattern of the names... do they end with a digit and a letter, or is that underscore character important too?
What is to be done with name values such as 12345a or 5678_b2 or 11_22_3b? How are those to be handled?
Seems to me like we want to use a SQL query like this:
SELECT SUBSTRING_INDEX(t.name,'_',1) AS `foo`
, 1 AS `count`
FROM (
SELECT 2 AS `id`, '1212_1a' AS `name`
UNION ALL SELECT 3, '1243_1a'
UNION ALL SELECT 7, '3142_1a'
UNION ALL SELECT 24, '1243_2a'
UNION ALL SELECT 30, '3142_2b'
UNION ALL SELECT 80, '2315_2b'
UNION ALL SELECT 136, '1243_3b'
UNION ALL SELECT 512, '8562_1a'
) t
GROUP BY `foo`
ORDER BY `foo`
The inline view (derived table) is in the query for testing. Replace that with the table reference:
SELECT SUBSTRING_INDEX(t.name,'_',1) AS `foo`
, 1 AS `count`
FROM mytable t
GROUP BY `foo`
ORDER BY `foo`
The expression for foo may need to be adjusted, to get desirable behavior with values that don't follow the regular pattern. Consider name values with no underscore, with more than one underscore, with endings other than a digit. We could also include a WHERE clause to exclude rows that don't follow the pattern,
WHERE t.name REGEXP '_[0-9][a-z]$'
(only name values that end with underscore, digit, lowercase letter).
Without a tested SQL query, I wouldn't know what to implement in CodeIgniter Query Builder.

MYSQL grouping by field that is not null

I have a table where a field is populated if the record is a duplicate. The code is already running, and properly checks for duplicates and is working.
The table looks like this:
id | dupe_ids | id_subscription
1 NULL 5343
2 3, 4 5343
3 2, 4 5343
4 2, 3 5343
5 NULL 5343
6 7 5343
7 6 5343
The query should return a count for the number of entries, but needs to group the duplicated ids. I need the query to group the records that have entries into one count, but somehow based on the duplicates. In the example above the count for subscription 5343, the count would be 4. Record 2 would count as one with 3 and 4 being skipped or grouped, and record 6 would count as one, with record 7 being grouped or skipped.
The query now looks like this:
SELECT app.id_subscription, app.id_site, app.id_customer, COUNT(*) AS app_count, site.url
FROM web_manager.app, web_manager.site
WHERE app.id_customer = :wm_id
AND (app.received_at BETWEEN :sdate AND :edate)
AND app.id_site = site.id
AND app.dupe_ids IS NULL
GROUP BY app.id_subscription
ORDER BY app_count DESC
If the values in dupe_ids is a list of numeric id values, and the list is always "in order" with the lowest value being the first in the list, as a dirty solution...
The query in my original answer (below) modified to replace the constant 0 with an expression like this: LEAST(a.id,SUBSTRING_INDEX(a.dupe_ids,',',1)+0).
That expression is saying: take the first value from the dupe_ids list, evaluate it in a numeric context, compare the numeric value to the id value from the row, and return the lower of the two.
SELECT COUNT(DISTINCT IF(a.dupe_ids IS NULL,a.id,LEAST(a.id,SUBSTRING_INDEX(a.dupe_ids,',',1)+0))) AS my_funky_cnt
, a.id_subscription
FROM web_manager.app a
JOIN web_manager.site s
ON s.id = a.id_site
WHERE ...
GROUP BY a.id_subscription
ORDER BY my_funky_cnt DESC
Again, removing the GROUP BY and the aggregate, to see what is actually being returned by the expression...
SELECT a.id
, a.dupe_ids
, a.id_subscription
, IF(a.dupe_ids IS NULL,a.id,LEAST(a.id,SUBSTRING_INDEX(a.dupe_ids,',',1)+0)) AS expr
FROM web_manager.app a
JOIN web_manager.site s
ON s.id = a.id_site
WHERE ...
ORDER BY a.id_subscription, a.dupe_ids IS NULL, a.id
we'd expect that to return:
id | dupe_ids | id_subscription | expr
2 3, 4 5343 2 -- id=2 is less than fv=3
3 2, 4 5343 2 -- fv=2 is less than id=3
4 2, 3 5343 2 -- fv=2 is less than id=4
6 7 5343 6 -- id=6 is less than fv=7
7 6 5343 6 -- fv=6 is less than id=7
1 NULL 5343 1
5 NULL 5343 5
So a GROUP BY id_subscription and COUNT(DISTINCT expr) would return a count of 4.
(this not tested)
This approach depends on dupes_id having the lowest id value listed first (first value in the list), evaluating that first value in a numeric context, and comparing that to the id value from the row.
If dupe_ids is an empty string, or starts with a comma, or the first non-blank characters can't be interpreted as a numeric value, then expr is going to return a 0.
EDIT
The original answer (below) was based on collapsing all of the rows with non-NULL values for a given id_subscription... returning a count of 3. The question has been updated, adding more example rows with non-NULL values which should not be collapsed together. Desired return for "count" is now 4. The query in the original answer would return a count of 3.
Getting a count of rows with a NULL value of dupe_ids is straightforward.
The sticky wicket is the bizarre contents of the dupe_ids column, the comma separated list of id values...
id dupe_ids
---- --------
2 '3,4'
3 '2,4'
4 '2,3'
6 '7'
7 '6'
This would be easier if we weren't dealing with a "comma separated list" of values. If we instead had foreign key references to the rows, in a separate table. Or, if we had some criteria other than the dupe_ids columns to identify rows that are "duplicates".
But, this wasn't the question asked. The question didn't ask if it would be better to avoid storing a comma separated list; whether there was a better approach.
The question leaves us dealing with a comma separated list. (It serves as an example of why we strongly recommend avoiding comma separated lists in the first place).
If we had an expression that has the values in dupe_ids along with the id value, together, so that we had identical values on the rows...
id dupe_ids expr
---- -------- ------
2 '3,4' '2,3,4'
3 '2,4' '2,3,4'
4 '2,3' '2,3,4'
6 '7' '6,7'
7 '6' '6,7'
Then we could use a COUNT(DISTINCT expr) to get us the return we're after. The ugly part is getting that value of expr. It would be easy to prepend or append id onto dupe_ids, but the resulting string values wouldn't be identical. The lists would be in a different order.
There's no simple builtin in function in MySQL to return the values shown for expr based on the contents of id and dupe_ids.
ORIGINAL ANSWER
The approach I would take is to use an expression, and count distinct values of that.
If dupe_ids is null, the return a unique value. If id is unique in the table, I would just use the value of that column. If dupe_ids is not null, then substitute a constant that is not a valid id value. Assuming id values are positive integers, I would use 0 or a negative value.
As an example:
SELECT COUNT(DISTINCT IF(a.dupe_ids IS NULL,a.id,0)) AS my_funky_cnt
, a.id_subscription
FROM web_manager.app a
JOIN web_manager.site s
ON s.id = a.id_site
WHERE ...
GROUP BY a.id_subscription
ORDER BY my_funky_cnt DESC
I'd verify the expression is "working" by first doing a query without the GROUP BY and aggregate...
SELECT a.id
, a.dupe_ids
, a.id_subscription
, IF(a.dupe_ids IS NULL,a.id,0) AS derived_col
FROM web_manager.app a
JOIN web_manager.site s
ON s.id = a.id_site
WHERE ...
ORDER BY a.id_subscription, a.dupe_ids IS NULL, a.id
We'd expect that to return:
id | dupe_ids | id_subscription | derived_col
1 NULL 5343 1
2 3, 4 5343 0
3 2, 4 5343 0
4 2, 3 5343 0
5 NULL 5343 5
So all of the rows with non-null dupe_ids have the same value, and the rows with NULL dupe_ids have a unique value.
And a COUNT(DISTINCT of that expression will return 3.

count comma-separated values from a column - sql

I want count the length of a comma separated column
I have use these
(LENGTH(Col2) - LENGTH(REPLACE(Col2,",","")) + 1)
in my select query.
Demo:
id | mycolumn
1 2,5,8,60
2 4,5,1
3 5,Null,Null
query result for first two row is coming correctly.for 1 = 4 ,2 = 3 but for 3rd row it is calculating null value also.
Here is what I believe the actual state of your data is:
id | mycolumn
1 2,5,8,60
2 4,5,1
3 NULL
In other words, the entire value for mycolumn in your third record is NULL, likely from doing an operation involving a NULL value. If you actually had the text NULL your current query should still work.
The way to get around this would be to use COALESCE(val, "") when handling the NULL values in your strings.
Crude way of doing it is to replace the occurances of ',Null' with nothing first:-
SELECT a.id, (LENGTH(REPLACE(mycolumn, ',Null', '')) - LENGTH(REPLACE(REPLACE(mycolumn, ',Null', ''),",","")) + 1)
FROM some_table a
If the values refer to the id of rows in another table then you can join against that table using FIND_IN_SET and then count the matches (assuming that the string 'Null' is not an id on that other table)
SELECT a.id, COUNT(b.id)
FROM some_table a
INNER JOIN id_list_table b
ON FIND_IN_SET(b.id, a.mycolumn)
GROUP BY a.id

mysql result from WHERE and the rest

assume that I have a table like this
table name = myTable
id
----
1
2
3
4
5
6
7
is there any way to fetch some rows with this query
SELECT * FROM `myTable` WHERE id IN (1,5,7) OR ... ;
and in fill the ... with any thing that give me the result for WHERE clause first,
and the rest of the rows after those rows???
somethig like this:
1,5,7,2,3,4,6
You don't do this with a where, you do this with an order by. Like this:
order by (id in (1, 5, 7)) desc
MySQL interprets boolean values as integers, with 0 being false and 1 being true. The desc will put the true values before the false ones.