retrieve specific records delimited in a table - mysql

I have a following table
SNo Data
1 |AA|B|C|D|E|
2 |AB|B|C|D|
3 |AA|C|
4 |AA|
5 |AA|AB|AC|C|
6 |AB|B|C|
data is delimited by "|". I understand that the table is denormalized but I cannot change the schema.
The user will give one more more inputs. For example if the user gives input as AA and C I have to retrieve only those rows where only AA and C occurs and not other rows
In this case my output will be
SNo Data
3 |AA|C|
The query that I have tried
Select * from table1 where data like %AA%C% will retrieve rows 1,2,3,5,6
Thanks

Assuming that within a record:
"blank" values are not to be ignored—i.e. |AA||C| is not the same as |AA|C|; and
none of the values are repeated—i.e. |AA|C|AA| will never occur.
Then you can perform pattern matches and test the total value length:
SELECT SNo
FROM my_table
WHERE data LIKE CONCAT('%|', 'AA', '|%')
AND data LIKE CONCAT('%|', 'C' , '|%')
AND CHAR_LENGTH(data) = 1 + CHAR_LENGTH('AA')
+ 1 + CHAR_LENGTH('C' )
+ 1
See it on sqlfiddle.

You can use wildcards, but you have to separate the expressions like this:
SELECT * FROM table1
WHERE data LIKE '%|AA|%' AND data LIKE '%|C|%'
This gets you all the records that contain both |AA| and |C|. However, to limit to rows that match only both:
SELECT * FROM table1
WHERE data LIKE '%|AA|%' AND data LIKE '%|C|%'
AND LENGTH(data) = 6
If you have just two, you may as well key them in and actually use an index on the data column though:
SELECT * FROM table1
WHERE data = '|AA|C|' OR data = '|C|AA|'
Which on older versions of MySQL can be optimized to:
SELECT * FROM table1
WHERE data = '|AA|C|'
UNION ALL
SELECT * FROM table1
WHERE data = '|C|AA|'
Alternatively, you could use a regular expression, which would not utilize an index.

A little idea using regular expressions:
select * from table1 where data regexp '(\\|AA\\|)+.*(\\|C\\|)+';

If I have understood correctly, what you are asking is "get the rows which matches input with delimiter".
So if input is "AA" and "c" then get rows where Data column will have result exactly like
|AA|C|
You can probably do like
select * from table1 where data = select concat('|',concat_ws('|','AA','C'),'|')

$whereClause = array();
foreach( $input AS $search ){
$whereClause[] = sprintf("data REGEXP '|?%s|?'", $search);
}
$sql = "SELECT * FROM tbl WHERE ".implode(" AND ", $whereClause);
Regular Expression Explained
This is the regular expression '|%s|' .

Related

Copy selected data and increment entry ID

I have selected my data with;
SELECT * FROM item_temp WHERE name LIKE '%starter%' AND Inventory LIKE '600';
I want to duplicate my selected data (Not overwrite it) multiply "entry" of every item in the query by 10.
As an example, the "entry" of one item is: 51327.
I want to make a copy of the item with an entry of 513270.
I have tried a few different methods but they've all resulted in errors and I feel like I'm at a brick wall.
Thanks in advance.
Something like this:
select (it.entry * 10 + n) as entry, . . . -- the rest of the columns go here
from (select 0 as n union all select 1 union all . . . select 9) n cross join
item_temp it
where it.name LIKE '%starter%' AND it.Inventory LIKE '600' ;
Use the INSERT INTO syntax
INSERT INTO table_name
<your query with same column order as table_name>;
Another option is making the destination table ex-novo with select ... into statement
SELECT *
into new_table
FROM item_temp
WHERE name LIKE '%starter%'
AND Inventory LIKE '600';
Use INSERT INTO with a SELECT that does the multiplication you need. You will have to write all columns on for the inserting table.
INSERT INTO item_temp (
entry
-- , other columns
)
SELECT
T.entry * 10 AS entry
-- , other columns
FROM
item_temp T
WHERE
name LIKE '%starter%' AND
Inventory LIKE '600';

How to grep the line by using the table contents in mysql?

here is mysql query which displays the entire table.
select * from datas;
name id dept
sen 1 cs
der 2 td
rest 3 ui
My query is i want to search by using table content(i.e in select statement i want to use the word rest and then display the table as follows).How can i do it in mysql?
Expected output:
name id dept
rest 3 ui
From your question, I don't understand why you can't just use the '=' :
SELECT * FROM datas
WHERE name = 'rest'
Although if you're truly looking for a grep equivalent, the LIKE statement is where it's at :
SELECT * FROM datas
WHERE name LIKE '%rest%' --to select lines where rest is contained in the string
Use '=' or LIKE to compare strings in SQL?
There many ways to do this
1.Use the WHERE clause just like this
SELECT * FROM datas WHERE id>2
2.Use LIMIT clause like this
SELECT * FROM datas LIMIT 2,1

How to compare two columns in mySql one of them Json

I have Two tables in mysql database and I want to compare two columns each of them in a different table first table name "oc_product_option_value" has column:
product_option_value_id
20
21
22
23
50
100
and second table "oc_cart" has cuolomn
option
{"20":"228","24":"229"}
I want compare two table and select data from first table where "product_option_value_id" in second table.
I tried:
SELECT * FROM oc_product_option_value
WHERE product_option_id IN
(SELECT REPLACE(REPLACE(REPLACE(REPLACE(OPTION,'{',''),'}',''),':',','),'"','')
as `option` FROM `oc_cart`)
and no result
* columns Structure
"product_option_value_id" is int
"option" is TEXT
Heum.. Not sure that it will do what you expect but I think it's a first step:
1/ Returns only rows wich have a matching value in second table (oc_cart)
SELECT *
FROM oc_product_option_value acpoa
JOIN oc_cart acc ON acc.option REGEXP concat('"', acpoa.product_option_value_id, '"');
Be careful about naming a column with a reserved MySQL word (option)
EDIT :
2/ If you want to display a "result" (final_kept_column) after this comparison in order to display "value_id" or "option" even if there's no matching value in oc_cart, you can try someting like this :
SELECT *,
CASE WHEN acc.option IS NULL
THEN acpoa.product_option_value_id
ELSE 0
END AS final_kept_column
FROM oc_product_option_value acpoa
LEFT JOIN oc_cart acc ON acc.option REGEXP concat('"', acpoa.product_option_value_id, '"');
Hope this help

Wildcard for a column name in the WHERE clause of a SELECT statement?

Is it possible to have a wildcard in a column name specified in the WHERE clause? I want to select something but only if a bunch of columns match a certain value (1 in this case). For example:
SELECT COUNT(id) FROM records WHERE *_check = 1
I have a bunch of columns that have _check as the suffix and it would be really nice to use something similar to the above code (which doesn't work).
You could query the information_schema to get the columns in one query
SELECT column_name FROM information_schema.columns
WHERE table_schema = 'foo'
AND table_name = 'bar'
AND column_name LIKE '%_check'
and build your query from the result (pseudo code)
query = "SELECT COUNT(id) FROM records WHERE ";
foreach columName in columnNames
query = query + " " + column_name + " = 1 OR "
next
query = TrimLastOr(query);
But I wouldn't recommend that because mysql information_schema query have a poor performance since they read from disk for every query.
Better: Use a view that returns
SELECT id FROM records WHERE col1_check=1 or col2_check=2 ...
so you can use it in your logic on multiple places, and only have to update the view if you add another _check column.
No.
If you want to do something like this, you need the equivalent of dynamic SQL.

Select query with IN clause: filling the blanks

I have the following problem with a MySQL query in C#:
Given a list of strings, I want to query the database for any rows that match said strings. The strings are unique in that each string matches no more than one row. Today, my query looks something like this:
SELECT Id FROM SomeTable
WHERE SomeColumn IN("foo", "bar", "baz")
Now, ideally I would like to be able to map the result from the query directly to the list of strings I supplied in the IN clause:
String Returned ID
------------------------------------------
foo 123
bar NULL <-- Missing row filled with NULL
baz 42
This works fine as long as all strings I pass to the query match a row. When one is missing, however, I would like to fill in the blank with a NULL as in the example above.
Is there any way to accomplish this?
Edit: I should probably have pointed out that the solution must scale to a lot of strings. The way I do it right now is that I pass 100 at a time through the IN clause.
You could do this:
SELECT
helper.SomeColumn,
SomeTable.Id
FROM
(
SELECT 'foo' AS SomeColumn
UNION SELECT 'bar'
UNION SELECT 'baz'
) AS helper
LEFT JOIN SomeTable ON SomeTable.SomeColumn = helper.SomeColumn
Of course you can create the helper table (as a temp table) beforehand instead of inline.
Anyway, maybe it is smarter and more efficient to just do the query you have (WHERE SomeColumn IN (...)) and simply figure out the missing rows in your application. You will loop over them anyway, so you will notice.
What you could do is SELECT the set of strings as a result set and then LEFT JOIN on SomeTable.SomeColumn.
Try this:
SELECT Id
FROM (
SELECT "foo" SomeColumn
UNION ALL
SELECT "bar" AS SomeColumn
UNION ALL
SELECT "baz" AS SomeColumn
) b
LEFT JOIN
SomeTable a
ON a.SomeColumn = b.SomeColumn