MySql select by column value. Separeta operator for columns - mysql

i have a mysql table like this
+-----+---------+-----------+-----------------+-------+
| id | item_id | item_type | field_name | data |
+-----+---------+-----------+-----------------+-------+
| 258 | 54 | page | field_interests | 1 |
| 257 | 54 | page | field_interests | 0 |
| 256 | 54 | page | field_author | value |
+-----+---------+-----------+-----------------+-------+
And, I need build query like this
SELECT * FROM `content_fields_data` WHERE
(`field_name`='field_author' AND `data` LIKE '%lu%')
AND
(`field_name`='field_interests' AND `data`='1')
But it returns 0 rows. If I change it or
SELECT * FROM `content_fields_data` WHERE
(`field_name`='field_author' AND `data` LIKE '%lu%')
**OR**
(`field_name`='field_interests' AND `data`='1')
I need to select all rows
WHERE
field_name.field_author.data LIKE '%text%'
AND
field_name.field_interests.data = '1'
I can explain it like a simple function:
IF table.field_name = 'field_author' THAN USE LIKE operator
IF table.field_name = 'field_interests' THAN USE equal(=) operator
Cant anybody help me?
Thanks.

I think you have to use OR instead of AND (otherwise it's clear you get no rows! a thing can't be equal to two different things...). So
SELECT * FROM table WHERE
(`field_name`='field_author' AND `field_author.data` LIKE '%jo%')
OR
(`field_name`='field_interests' AND `field_interests.data`='0')
OR
(`field_name`='field_interests' AND `field_interests.data`='1')

Related

SQL: How to get last date in groupby for getting unique records?

I am working on a data where I have to use multiple joins and figures out that one of the table is producing duplicates as I applied Group by on dates as well and b/c of different dates my query takes in duplicate values.
I wrote following query
SELECT
ll.ID,
ll.EST_DT
gg.col1 ,
ll.EST_CLAIM_DT,
gg.col2
FROM table gg
inner join
(select substr(ID,1,instr(ID,'-',7)-1) EST_ID,
max(est_dt) as EST_DT,
max(EST_CLAIM_DT) as EST_CLAIM_DT
from table group by substr(gg.ID,1,instr(ID,'-',7)-1)) ll
on substr(ID,1,instr(gg.ID,'-',7)-1)=substr(ll.ID,1,instr(ll.ID,'-',7)-1)
GROUP BY
ll.ID,
ll.EST_DT
gg.col1 ,
ll.EST_CLAIM_DT,
gg.col2
Table looks like this:
+-----------------+------------+----------------+------+------+
| ID | est_date | est_claimed_dt | col1 | col2 |
+-----------------+------------+----------------+------+------+
| EST-U-1040452-1 | 28/02/2019 | 28/02/2019 | 50 | 50 |
| EST-U-1040452-2 | 5/10/2020 | 5/10/2020 | 50 | 50 |
+-----------------+------------+----------------+------+------+
Desired output
+---------+-----------+----------------+------+------+
| ID | est_date | est_claimed_dt | col1 | col2 |
+---------+-----------+----------------+------+------+
| 1040452 | 5/10/2020 | 5/10/2020 | 50 | 50 |
+---------+-----------+----------------+------+------+
I get this error as well
Negative sub string length not allowed
P.S. I have search SO for this issue and it helped but couldn't get it to work.

How to inner join result of stored function?

I am searching for all day with no success so I decided to ask.
I will very simplify structure as much as possible to ask for essence.
I have function:
mysql> SELECT set_of_ids_to_names('1:2:3:4:5', ':') AS `res`;
+-------------------------------+
| res |
+-------------------------------+
| NameA:NameB:NameC:NameD:NameE |
+-------------------------------+
I have table:
mysql> SELECT * FROM `tbl_tool`;
+----+-----------------+---------+
| ID | Tool | ID_name |
+----+-----------------+---------+
| 1 | Tool_1 | 1:2:3:4 |
| 2 | Tool_2 | 2:4:5 |
| 3 | Tool_3 | 4:5 |
| 4 | Tool_4 | 3 |
+----+-----------------+---------+
The result I would like to achieve is to have view called 'v_tool' so once I selet it I get:
mysql> SELECT * FROM `v_tool`;
+----+-----------------+-------------------------+
| ID | Tool | Name |
+----+-----------------+-------------------------+
| 1 | Tool_1 | NameA:NameB:NameC:NameD |
| 2 | Tool_2 | NameB:NameD:NameE |
| 3 | Tool_3 | NameD:NameE |
| 4 | Tool_4 | NameC |
+----+-----------------+-------------------------+
This what I tried is:
SELECT `tbl_tool`.`ID`, `tbl_tool`.`Tool`, `Name` FROM `tbl_tool`
INNER JOIN (SELECT set_of_ids_to_names((SELECT `ID` FROM `tbl_tool` WHERE `ID` = `tbl_tool`.`ID`), ':') AS `Name`) AS `aaa`
I know that it is wrong, but I just could not find idea how to pass proper value to function 'set_of_ids_to_names'.
Big thank you in advance.
Looking at the original function call you made:
SELECT set_of_ids_to_names('1:2:3:4:5', ':') AS `res`
It is important to note the function call appears in the SELECT clause, not in the FROM clause.
This suggests set_of_ids_to_names is a scalar function, not a table-valued function.
When querying table tbl_tool, you can do the exact same thing: call set_of_ids_to_names in the SELECT clause.
SELECT Tool, set_of_ids_to_names(ID_name, ':') AS Name
FROM tbl_tool
For table-valued functions, the situation is different of course. SQL Server has CROSS APPLY for that, in MySQL you'd probably have to join the table with a subquery encapsulating the function call.

MySQL - add text prefix before column name in SELECT statement

Here is my table:
| ID | NUMBER |
| 1 | 523 |
| 2 | 293 |
| 3 | 948 |
And now, I want to get all NUMBER values but I want to add in result two numbers - 48 - (without upadting existing results). So finally I want print these results:
| NUMBER |
| 48523 |
| 48293 |
| 48948 |
So I need a query, something like this:
SELECT '48' + `number` FROM `table`
but this query doesn't work fine (this query only update column name from NUMBER to 48 + NUMBER).
Any ideas?
Thanks.
You need CONCAT
SELECT CONCAT('48' , `number`) AS number FROM table
Demo

MySQL: optimize query for scoring calculation

I have a data table that I use to do some calculations. The resulting data set after calculations looks like:
+------------+-----------+------+----------+
| id_process | id_region | type | result |
+------------+-----------+------+----------+
| 1 | 4 | 1 | 65.2174 |
| 1 | 5 | 1 | 78.7419 |
| 1 | 6 | 1 | 95.2308 |
| 1 | 4 | 1 | 25.0000 |
| 1 | 7 | 1 | 100.0000 |
+------------+-----------+------+----------+
By other hand I have other table that contains a set of ranges that are used to classify the calculations results. The range tables looks like:
+----------+--------------+---------+
| id_level | start | end | status |
+----------+--------------+---------+
| 1 | 0 | 75 | Danger |
| 2 | 76 | 90 | Alert |
| 3 | 91 | 100 | Good |
+----------+--------------+---------+
I need to do a query that add the corresponding 'status' column to each value when do calculations. Currently, I can do that adding the following field to calculation query:
select
...,
...,
[math formula] as result,
(select status
from ranges r
where result between r.start and r.end) status
from ...
where ...
It works ok. But when I have a lot of rows (more than 200K), calculation query become slow.
My question is: there is some way to find that 'status' value without do that subquery?
Some one have worked on something similar before?
Thanks
Yes, you are looking for a subquery and join:
select s.*, r.status
from (select s.*
from <your query here>
) s left outer join
ranges r
on s.result between r.start and r.end
Explicit joins often optimize better than nested select. In this case, though, the ranges table seems pretty small, so this may not be the performance issue.

MySQL query - only exact result or every choice

I've a query that I need some help with -
As part of a form I've got a serial number field that is populated if there is a serial number, blank if it's not, or no result if it's an invalid serial number.
select *
from cust_site_contract as cs
where cs.serial_no = 'C20050' or (cs.serial_no <> 'C20050' and if(cs.serial_no = 'C20050',1,0)=0)
limit 10;
Here's a sample of the regular data:
+----------------------+-----------+-----------+-----------
| idcust_site_contract | system_id | serial_no | end_date
+----------------------+-----------+-----------+-----------
| 561315 | SH001626 | C19244 | 2009-12-21
| 561316 | SH001626 | C19244 | 2010-06-30
| 561317 | SH002125 | C19671 | 2010-05-31
| 561318 | SH001766 | C14781 | 2010-09-25
| 561319 | SH001766 | C14781 | 2011-02-15
| 561320 | SH002059 | C19020 | 2008-07-09
| 561321 | SH002639 | C18889 | 2008-03-31
| 561322 | SH002639 | C18889 | 2008-06-30
| 561323 | SH002715 | C20051 | 2010-04-30
| 561324 | SH002719 | C20057 | 2010-04-30
And an exact result would look something like this:
| 561487 | SH002837 | C20050 | 2012-07-04
I was writing this as a subquery so I could match the system_ids to customer and contract names, but realised I was getting garbage pretty early on.
I'm tempted to try and simplify it by saying the third case might not hold true (i.e. if it's an invalid serial number, allow the choice of any customer name and simply flag it in the data)
Has anyone got any ideas of where I'm going wrong? The combination of conditions is clearly wrong, and I can't work out how to make each side of the or statement mutually exclusive
Even if I try to evaluate only the if(sn = 'blah') I get the wrong result for obvious reasons, but can't think of a sane way to express it.
Many thanks
Scott
If there is is no contract with a serial number of C20050, this query will return all rows, otherwise, it will return only one row where serial_no is C20050:
SELECT a.*
FROM cust_site_contract a
INNER JOIN
(
SELECT COUNT(*) AS rowexists
FROM cust_site_contract
WHERE serial_no = 'C20050'
) b ON b.rowexists = 0
UNION ALL
(
SELECT *
FROM cust_site_contract
WHERE serial_no = 'C20050'
LIMIT 1
)
If you just write the query as below you will get blank if doesn't exists or it's an invalid serial number.
select cs.serial_no from cust_site_contract as cs where cs.serial_no = 'C20050'