MYSQL passing string into IN operator not working in nodejs - mysql

by right SELECT topicFollowed FROM User WHERE id = 10000) return "[0,2]" <<-string
but when i execute SELECT * from News WHERE topicId IN (SELECT topicFollowed FROM User WHERE id = 10000) only 0 is pass in and 2 is not. i cant figure out why. it only return topicId that is 0

Your IN list consists of exactly one item, a string of the form '[0,2]'. If that is what topicId looks like, then your query will work.
In other words, you have a problem with your data structure. You shouldn't be storing lists of things in strings. The proper data structure would have two rows, one for each of the ids in the list.
Sometimes, you are stuck with someone else's bad data design. You can do what you want, by doing something like this:
SELECT n.*
from News n
WHERE EXISTS (SELECT 1
FROM user u
WHERE find_in_set(topicId, replace(replace(topicFollowed, '[', ''), ']', '') AND
id = 10000
);

Related

How to retrieve data from mysql db by passing an array

I have an dynamic array of id which is passed by frontend. I need to fetch data from mysql db where the tuples ids are match with the ids which i pass.
Example Id array: [6, 7, ...]
The number of items can be vary according to different requests.
SELECT expense_type, expense_category FROM expense_type WHERE expense_category_id=id1 OR expense_category_id=id2;
id1, id2 are the ids which comes from the frontend. (6,7,...)
There can be multiple ids which comes from the frontend.
could i please know is there a way to fetch data from one query in such situation.
Or else do i have to write multiple queries to execute?
You need to make query by using that multiple ids's array.
something like below
query = 'SELECT expense_type, expense_category FROM expense_type WHERE expense_category_id IN (`;
forEach(ids as id) {
query += id + ','
}
run query..
To select data based on an array of values you can use the IN-keyword. In your case it would look like this:
SELECT expense_type, expense_category
FROM expense_type
WHERE expense_category_id IN ('id1', 'id2');
you can easily use an IN.
also try to use Join. so the accuracy of the query will get increase.
SELECT expense_type, expense_category
FROM expense_type
WHERE expense_category_id IN ('id1', 'id2');

Print results of multiple SQL queries as one result

So I have 3 SQL query results (example code below). I want the results to be displayed either as different columns or different tables. Is this even possible? If yes, please help as to how. The results are unrelated to each other
SELECT RouterName, RouterType, Loopback100, Loopback200, ResiliencyGroup,
DeploymentStatus
FROM Routers
WHERE RouterName = 'PE23-SNG-AP'
SELECT ARouter, AInterface, BRouter, BInterface
FROM netplan.LinksPACSLcl
WHERE ARouter = 'PE23-SNG-AP' OR Brouter = 'PE23-SNG-AP'
This is, I believe, a job for JOIN. With respect if you don't know about JOIN you should study it; it's a core feature of SQL. It combines rows from multiple tables into single output rows.
Try something like this
SELECT i.RouterName, i.RouterType, i.Loopback100, i.Loopback200,
i.ResiliencyGroup i.DeploymentStatus,
j.ARouter, j.AInterface, j.BRouter, j.BInterface
FROM Routers i
LEFT JOIN netplan.LinksPACSLcl j (ON i.RouterName = j.ARouter
OR i.RouterName = j.BRouter)
WHERE RouterName = 'PE23-SNG-AP'
This generates a result set with the items from both your first and second tables, assiging the alias names i and j to those tables. The LEFT JOIN operation allows information from the first table to be shown even without anything matching it in the second table.
You should use UNION. This is a working sample. The important part is Column names. Check carefully the usage of col1 with as
select UserName as col1 from Users
union
select FeatureName as col1 from Features
union
select TopicName as col1 from Topics
If you can accept a json result ;)
SELECT JSON_ARRAY_APPEND('[]', '$',
JSON_EXTRACT((SELECT concat('[',
group_concat(
JSON_OBJECT('RouterName' , `RouterName`,
'RouterType' , `RouterType`,
'Loopback100' , `Loopback100`,
'Loopback200' , `Loopback200`,
'ResiliencyGroup' , `ResiliencyGroup`,
'DeploymentStatus', `DeploymentStatus`)
SEPARATOR ','),
']')
FROM Routers
WHERE RouterName = 'PE23-SNG-AP'), '$[*]'), '$',
JSON_EXTRACT((SELECT concat('[',
group_concat(
JSON_OBJECT('ARouter' , `ARouter`,
'AInterface', `AInterface`,
'BRouter' , `BRouter`,
'BInterface', `BInterface`)
SEPARATOR ','),
']')
FROM netplan.LinksPACSLcl
WHERE ARouter = 'PE23-SNG-AP'
OR Brouter = 'PE23-SNG-AP'), '$[*]'));
If you use sql server, you can use SELECT ... FOR XML RAW...
https://learn.microsoft.com/en-us/sql/relational-databases/xml/example-specifying-a-root-element-for-the-xml-generated-by-for-xml

MySQL: Select unique field and return all other columns as well + if specific column is not 0 - return that

I can't figure out how to get this done.
Basically I am making message system, I have this table:
Basically I am trying to print out threads, like every distinct msgfrom is a new thread.
Thread should basically say:
[(Sender Name) (Last Message (ORDER BY id DESC)) ([if at least one
message has msgread=0 then say You have unread messages])
I've tried this so far:
SELECT id, msgfrom, message, date,
IF(msgread='0', 'unread', 'read') AS msr
FROM pmessages WHERE msgto=$userId GROUP BY msgfrom
But that returns:
message from: Username (this is msgfrom 1)
read
message from: Username (this is msgfrom 2)
unread
Even though msgfrom1 has 1 unread message, it says read (I assume it takes first result). So in basic:
SELECT UNIQUE msgrom
ORDER BY id DESC
IF at least ONE msgread = 0
return * + set msgread=0 (unread)
It's a bit hard to explain, sorry if it's a bit unclear.
You can't reliably GROUP your data together as you attempted in the first SQL.
If I understand you correctly, you want to differentiate the posts which are read and unread?
SELECT id
, msgfrom
, message
, date
, CASE WHEN msgread = 0 THEN 'unread' ELSE 'read' AS msgread
FROM pmessages
WHERE msgfrom IN ( SELECT DISTINCT msgfrom
FROM pmessages
WHERE msgto = ?
)
ORDER BY msgfrom ASC
, date DESC
Please make sure you use placeholders in your code (assuming PHP) rather than passing the variable in directly into the query, to prevent SQL Injection.
Let me know how you get on.

How can I sanitize my DB from these duplicates

I have a table with the following fields:
id | domainname | domain_certificate_no | keyvalue
An example for the output of a select statement can be as:
'57092', '02a1fae.netsolstores.com', '02a1fae.netsolstores.com_1', '55525772666'
'57093', '02a1fae.netsolstores.com', '02a1fae.netsolstores.com_2', '22225554186'
'57094', '02a1fae.netsolstores.com', '02a1fae.netsolstores.com_3', '22444356259'
'97168', '02aa6aa.netsolstores.com', '02aa6aa.netsolstores.com_1', '55525772666'
'97169', '02aa6aa.netsolstores.com', '02aa6aa.netsolstores.com_2', '22225554186'
'97170', '02aa6aa.netsolstores.com', '02aa6aa.netsolstores.com_3', '22444356259’
I need to sanitize my db such that: I want to remove the domain names that have repeated keyvalue for the first domain_certificate_no (i.e, in this example, I look for the field domain_certificate_no: 02aa6aa.netsolstores.com_1, since it is number 1, and has repeated value for the key, then I want to remove the whole chain which is 02aa6aa.netsolstores.com_2 and 02aa6aa.netsolstores.com_3 and this by deleting the domain name that this chain belongs to which is 02aa6aa.netsolstores.com.
How can I automate the checking process for the whole DB. So, I have a query that checks any domain name in the pattern ('%.%.%) EDIT: AND they have share domain name (in this ex: netsolstores.com) , if it finds cert no. 1 that belongs to this domain name has a repeated key value, then delete. Otherwise no. Please, note tat, it is ok for domain_certificate_no to have repeated value if it is not number 1.
EDIT: I only compare the repeated valeues for the same second level domain name. Ex: in this question, I compare the values that share the domain name: .netsolstores.com. If I have another domain name, with sublevel domains, I do the same. But the point is that I don't need to compare the whole DB. Only the values with shared domain name (but different sub domain).
I'm not sure what happens with '02aa6aa.netsolstores.com_1' in your example.
The following keeps only the minimum id for any repeated key:
with t as (
select t.*,
substr(domain_certificate_no,
instr(domain_certificate_no, '_') + 1, 1000) as version,
left(domain_certificate_no, instr(domain_certificate_no, '_') - 1) as dcn
from t
)
select t.*
from t join
(select keyvalue, min(dcn) as mindcn
from t
group by keyvalue
) tsum
on t.keyvalue = tsum.keyvalue and
t.dcn = tsum.mindcn
For the data you provide, this seems to do the trick. This will not return the "_1" version of the repeats. If that is important, the query can be pretty easily modified.
Although I prefer to be more positive (thinking about the rows to keep rather than delete), the following should delete what you want:
with t as (
select t.*,
substr(domain_certificate_no,
instr(domain_certificate_no, '_') + 1, 1000) as version,
left(domain_certificate_no, instr(domain_certificate_no, '_') - 1) as dcn
from t
),
tokeep as (
select t.*
from t join
(select keyvalue, min(dcn) as mindcn
from t
group by keyvalue
) tsum
on t.keyvalue = tsum.keyvalue and
t.dcn = tsum.mindcn
)
delete from t
where t.id not in (select id from tokeep)
There are other ways to express this that are possibly more efficient (depending on the database). This, though, keeps the structure of the original query.
By the way, when trying new DELETE code, be sure that you stash a copy of the table. It is easy to make a mistake with DELETE (and UPDATE). For instance, if you leave out the WHERE clause, all the rows will disappear, after the long painful process of logging all of them. You might find it faster to simply select the desired results into a new table, validate them, then truncate the old table and re-insert them.

Return zero when records not found

Im making a table generator as a school project.
In MySQL I have 3 tables namely process,operation,score. Everything looked fine until i tested out my "ADD column" button in the web app.
Previous saved data should be read properly but also include the new column in the format, problem is the previous data queried does not include any values for the new table, so I intended it to return a score of 0 if no records were found, tried IFNULL & COALESCE but nothing happens(maybe im just using it wrong)
process - processID, processName
operation - operationID, operationName
score - scoreID, score, processID, operationID, scoreType (score
types are SELF,GL,FINAL)
ps = (PreparedStatement)dbconn.prepareStatement("SELECT score FROM score WHERE processID=? and operationID=? and type=?ORDER BY processid");
here's a pic of a small sample http://i50.tinypic.com/2yv3rf9.jpg
The reason that IFNULL doesn't work is that it only has an effect on values. A result set with no rows has no values, so it does nothing.
First, it's probably better to do this on the client than on the server. But if you have to do it on the server, there's a couple of approaches I can think of.
Try this:
SELECT IFNULL(SUM(score), 0) AS score
FROM score
WHERE processID=? and operationID=? and type=?
ORDER BY processid
The SUM ensures that exactly one row will be returned.
If you need to return multiple rows when the table contains multiple matching rows then you can use this (omitting the ORDER BY for simplicity):
SELECT score
FROM score
WHERE processID = ? and operationID = ? and type = ?
UNION ALL
SELECT 0
FROM (SELECT 0) T1
WHERE NOT EXISTS
(
SELECT *
FROM score
WHERE processID = ? and operationID = ? and type = ?
)