Null result while use and operator in MYSQL IN - php

This is my query to get filter data from user table where category will fetch from another table.
SELECT * FROM jobfia_users
WHERE country_id='4'
and user_id IN (SELECT worker_id
FROM jobfia_worker_skills
WHERE skill_id = '42'
)
This is not giving any error, but not return any row also.
while there are lots of records are available in table using this filter.
Can any one help please ?

Additionally to the quotes surrounding your INT ids, your query will be better expressed like this :
SELECT u.*
FROM jobfia_users u
INNER JOIN jobfia_worker_skills ws
ON ws.worker_id=u.user_id AND ws.skill_id = 42
WHERE u.country_id=4

If your country_id and skill_id are int type, remove ' around values.
SELECT * FROM jobfia_users
WHERE country_id=4
and user_id IN (SELECT worker_id
FROM jobfia_worker_skills
WHERE skill_id = 42
)

Tested your code with and without '' and it works. Make sure you have data and you did not misspell some column name.
Maybe you have collision of some column names. Try to use this syntax:
\`table_name\`.\`column_name\`
Code:
SELECT *
FROM `jobfia_users`
WHERE `jobfia_users`.`country_id`='4'
AND `jobfia_users`.`user_id` IN (SELECT `jobfia_worker_skills`.`worker_id`
FROM `jobfia_worker_skills`
WHERE `jobfia_worker_skills`.`skill_id` = '42')

Related

Which Clause to use instead of IN Clause in MYSQL

My Question is
Which Clause use instead of IN Clause in MYSQL with PHP
Because IN Clause Limit 1024 character.
My Character limit exceed to 1024 character.
SELECT * FROM TblUser
WHERE Status != 'Deleted' AND UserId IN (0,10,11,12,13,14,15,22,45,114,144,155,156,167,211,439,440,441,443,445,450,455,456,457,458,459,1111,1154,1156,1165,1451,1541,11111,11112,11113,11114,11115,11116,11117,11118,11119,11656,15451,16561,17671,18781,33131,33311,33411,54511,111110,111111,111112,111113,111114,111115,111116,111117,111118,111119,111120,111121,111122,111123,111124,111125,111126,111127,111128,111129,111130,111131,111132,111133,111134,111135,111136,111137,111138,111139,111140,111141,111142,111143,111144,111145,111146,111147,111148,111149,111150,111151,111152,111153,111154,111155,111156,111157,111158,111159,111160,111161,111162,111163,111164,111165,111166,111167,111168,111169,111170,111171,111172,111173,111174,111175,111176,111177,111178,111179,111180,111181,111182,111183,111184,111185,111186,111187,111188,111189,111190,111191,111192,111193,111194,111195,111196,111197,111198,111199,1111100,11112101,11112102,11112103,11112104,11112105,11112106,11112107,11112108,11112109,11112110,11112111,11112112,11112113,11112114,11112115,11112116,11112117,11112118,11112119,11112120,11112121,11112122,11112123,11112124,11112125,11112126,11112127,11112128,11112129,11112130,11112131,11112132,11112133,11112134,11112135,11112136,11112137,11112138,11112139,11112140,11112141,11112142,11112143,11112144,11112145,11112146,11112147,11112148,11112149,11112150,11112151,11112152,11112153,11112154,11112155,11112156,11112157,11112158,11112159,11112160,11112161,11112162,11112163,11112164,11112165,11112166,11112167,11112168,11112169,11112170,11112171,11112172,11112173,11112174,11112175,11112176,11112177,11112178,11112179,11112180,11112181,11112182,11112183,11112184,11112185,11112186,11112187,11112188,11112189,11112190,11112191,11112192,11112193,11112194,11112195,11112196,11112197,11112198,11112199,11112200);
Please help Which Clause use instead of IN Clause in MYSQL with PHP?
Is the list of values that are used in the IN statement always the same, or is that list the result of some other query? If the latter is the case, you could use that query as a subquery:
SELECT * FROM tbluser
WHERE status != 'Deleted'
AND userid IN
( SELECT userid FROM sometable WHERE ... )
Yes you are limited within an IN statement, one thing you could do is create a temporary table which stores the values.
CREATE TEMPORARY TABLE IF NOT EXISTS temp AS (SELECT userid FROM tbluser);
In PHP create your INSERT INTO script:
$str = '0,10,11,12,13,14,15,22,45,114,144,155,156,167,211,439,440,441,443,445,450,455,456,457,458,459,1111,1154,1156,1165,1451,1541,11111,11112,11113,11114,11115,11116,11117,11118,11119,11656,15451,16561,17671,18781,33131,33311,33411,54511,111110,111111,111112,111113,111114,111115,111116,111117,111118,111119,111120,111121,111122,111123,111124,111125,111126,111127,111128,111129,111130,111131,111132,111133,111134,111135,111136,111137,111138,111139,111140,111141,111142,111143,111144,111145,111146,111147,111148,111149,111150,111151,111152,111153,111154,111155,111156,111157,111158,111159,111160,111161,111162,111163,111164,111165,111166,111167,111168,111169,111170,111171,111172,111173,111174,111175,111176,111177,111178,111179,111180,111181,111182,111183,111184,111185,111186,111187,111188,111189,111190,111191,111192,111193,111194,111195,111196,111197,111198,111199,1111100,11112101,11112102,11112103,11112104,11112105,11112106,11112107,11112108,11112109,11112110,11112111,11112112,11112113,11112114,11112115,11112116,11112117,11112118,11112119,11112120,11112121,11112122,11112123,11112124,11112125,11112126,11112127,11112128,11112129,11112130,11112131,11112132,11112133,11112134,11112135,11112136,11112137,11112138,11112139,11112140,11112141,11112142,11112143,11112144,11112145,11112146,11112147,11112148,11112149,11112150,11112151,11112152,11112153,11112154,11112155,11112156,11112157,11112158,11112159,11112160,11112161,11112162,11112163,11112164,11112165,11112166,11112167,11112168,11112169,11112170,11112171,11112172,11112173,11112174,11112175,11112176,11112177,11112178,11112179,11112180,11112181,11112182,11112183,11112184,11112185,11112186,11112187,11112188,11112189,11112190,11112191,11112192,11112193,11112194,11112195,11112196,11112197,11112198,11112199,11112200';
$ids = explode(',', $str);
foreach ($ids as $value){
echo 'INSERT INTO temp VALUES(' . $value . '); </br>';
}
But change the echo for the mysqli query.
Then:
SELECT * FROM tbluser u
where status !='Deleted'
And exists(select * from temp u1 where u1.userid = u.userid)
Or you can do an inner join temp u1 on u1.userid = u.userid
#Abid as you mentioned your question in this case #Guss is right.
What i am thinking if values mentioned IN clause comes from GROUP_CONCAT then might be possible duplicate values exist with comma seperated. So to remove duplicacy we can use DISTINCT.
For example :
SELECT GROUP_CONCAT(UserId) FROM sometable
Above query can give duplicate values.
SELECT GROUP_CONCAT(DISTINCT UserId) FROM sometable
SELECT t1.UserRoleId, t1.EntityId, GROUP_CONCAT( DISTINCT t1.PermissionId ) AS Permissions
FROM userpermission t1, bill_companies t2
WHERE t1.Status = 'Active'
AND t2.status = 'Active'
AND UserGroupId
IN ( 84, 85, 86 )
LIMIT 0 , 30
Above query gives you userid's without duplicacy. This can also reduce the size of comma seperated ids.
Hope this will help.
You could create groups using php if there are Ids which follow by increment e. g. 1,2,3 and replace them by a OR (id >= 1 AND id <= 3)
Alternative approach:
Search Max and Min ID in your List and query using an interval (greater than and less than) and use php to do the job.
If you really want to avoid using IN then you could use FIND_IN_SET():-
SELECT * FROM TblUser
WHERE Status != 'Deleted' AND FIND_IN_SET(UserId, '0,10,11,12,13,14,15,22,45,114,144,155,156,167,211,439,440,441,443,445,450,455,456,457,458,459,1111,1154,1156,1165,1451,1541,11111,11112,11113,11114,11115,11116,11117,11118,11119,11656,15451,16561,17671,18781,33131,33311,33411,54511,111110,111111,111112,111113,111114,111115,111116,111117,111118,111119,111120,111121,111122,111123,111124,111125,111126,111127,111128,111129,111130,111131,111132,111133,111134,111135,111136,111137,111138,111139,111140,111141,111142,111143,111144,111145,111146,111147,111148,111149,111150,111151,111152,111153,111154,111155,111156,111157,111158,111159,111160,111161,111162,111163,111164,111165,111166,111167,111168,111169,111170,111171,111172,111173,111174,111175,111176,111177,111178,111179,111180,111181,111182,111183,111184,111185,111186,111187,111188,111189,111190,111191,111192,111193,111194,111195,111196,111197,111198,111199,1111100,11112101,11112102,11112103,11112104,11112105,11112106,11112107,11112108,11112109,11112110,11112111,11112112,11112113,11112114,11112115,11112116,11112117,11112118,11112119,11112120,11112121,11112122,11112123,11112124,11112125,11112126,11112127,11112128,11112129,11112130,11112131,11112132,11112133,11112134,11112135,11112136,11112137,11112138,11112139,11112140,11112141,11112142,11112143,11112144,11112145,11112146,11112147,11112148,11112149,11112150,11112151,11112152,11112153,11112154,11112155,11112156,11112157,11112158,11112159,11112160,11112161,11112162,11112163,11112164,11112165,11112166,11112167,11112168,11112169,11112170,11112171,11112172,11112173,11112174,11112175,11112176,11112177,11112178,11112179,11112180,11112181,11112182,11112183,11112184,11112185,11112186,11112187,11112188,11112189,11112190,11112191,11112192,11112193,11112194,11112195,11112196,11112197,11112198,11112199,11112200')
However the only limit for the number of entries in an IN clause is set by max_allowed_packet (as others have stated) and the same restriction would apply to this.
max_allowed_packet

Mysql query "WHERE 2 IN (`column`)" not working

I want to execute a query where I can find one ID in a list of ID.
table user
id_user | name | id_site
-------------------------
1 | james | 1, 2, 3
1 | brad | 1, 3
1 | suko | 4, 5
and my query (doesn't work)
SELECT * FROM `user` WHERE 3 IN (`id_site`)
This query work (but doesn't do the job)
SELECT * FROM `user` WHERE 3 IN (1, 2, 3, 4, 6)
That's not how IN works. I can't be bothered to explain why, just read the docs
Try this:
SELECT * FROM `user` WHERE FIND_IN_SET(3,`id_site`)
Note that this requires your data to be 1,2,3, 1,3 and 4,5 (ie no spaces). If this is not an option, try:
SELECT * FROM `user` WHERE FIND_IN_SET(3,REPLACE(`id_site`,' ',''))
Alternatively, consider restructuring your database. Namely:
CREATE TABLE `user_site_links` (
`id_user` INT UNSIGNED NOT NULL,
`id_site` INT UNSIGNED NOT NULL,
PRIMARY KEY (`user_id`,`site_id`)
);
INSERT INTO `user_site_links` VALUES
(1,1), (1,2), (1,3),
(2,1), (2,3),
(3,4), (3,5);
SELECT * FROM `user` JOIN `user_site_links` USING (`id_user`) WHERE `id_site` = 3;
Try this: FIND_IN_SET(str,strlist)
NO! For relation databases
Your table doesn't comfort first normal form ("each attribute contains only atomic values, and the value of each attribute contains only a single value from that domain") of a database and you:
use string field to contain numbers
store multiple values in one field
To work with field like this you would have to use FIND_IN_SET() or store data like ,1,2,3, (note colons or semicolons or other separator in the beginning and in the end) and use LIKE "%,7,%" to work in every case. This way it's not possible to use indexes[1][2].
Use relation table to do this:
CREATE TABLE user_on_sites(
user_id INT,
site_id INT,
PRIMARY KEY (user_id, site_id),
INDEX (user_id),
INDEX (site_id)
);
And join tables:
SELECT u.id, u.name, uos.site_id
FROM user_on_sites AS uos
INNER JOIN user AS u ON uos.user_id = user.id
WHERE uos.site_id = 3;
This way you can search efficiently using indexes.
The problem is that you are searching within several lists.
You need something more like:
SELECT * FROM `user` WHERE id_site LIKE '%3%';
However, that will also select 33, 333 and 345 so you want some more advanced text parsing.
The WHERE IN clause is useful to replace many OR conditions.
For exemple
SELECT * FROM `user` WHERE id IN (1,2,3,4)
is cleaner than
SELECT * FROM `user` WHERE id=1 OR id=2 OR id=3 OR id=4
You're just trying to use it in a wrong way.
Correct way :
WHERE `field` IN (list_item1, list_item2 [, list_itemX])

Get one value when cell input is same

I would like to get one value instead of all values when they have the same name.
within an sql query. Im using fullcalendar. and have two tables one for the events(evenement) and one for the receiver(evenementontvanger).
evenementontvanger:
id idEvent
1 231
2 231
3 231
evenement:
id title
231 hello
I would like to show only one title not 3
my sql query:
"SELECT
*
FROM
`evenement`
JOIN
`evenementontvanger` ON `evenementontvanger`.`idEvent` = `evenement`.`id`
WHERE
`idEvent` = `evenement`.`id`"
You can use distinct to do so as
SELECT distinct `evenementontvanger`.`idEvent`,`evenement`.`title`
FROM
`evenement`
JOIN
`evenementontvanger` ON `evenementontvanger`.`idEvent` = `evenement`.`id`
WHERE
`idEvent` = `evenement`.`id`;
How ever the above will not bother about idWerknemer and if you want to display them as group use Group_concat as
SELECT `evenementontvanger`.`idEvent`,
`evenement`.`title`,
group_concat(`evenementontvanger`.`idWerknemer`) as `idWerknemer`
FROM
`evenement`
JOIN
`evenementontvanger` ON `evenementontvanger`.`idEvent` = `evenement`.`id`
WHERE
`idEvent` = `evenement`.`id`
Group By `evenementontvanger`.`idEvent`
Check the demo here http://sqlfiddle.com/#!2/290b4/13
Use SELECT DISTINCT on your query to eliminate duplicates :
The ALL and DISTINCT options specify whether duplicate rows should be
returned. ALL (the default) specifies that all matching rows should be
returned, including duplicates. DISTINCT specifies removal of
duplicate rows from the result set. It is an error to specify both
options. DISTINCTROW is a synonym for DISTINCT.
From MySQL docs
use either top 1
OR
select distinct

trying to output the correct value from SQL query from comparing a different table

I'm very new with SQL and need assistance on how I can accomplish this task using the correct query.
I have 2 tables that I need to use. Table "TB1" has:
id Name
1 bob
2 blow
3 joe
table "TB2" has:
compid property
1 bob
2 blow
I am trying to get which compid is missing in "TB2" and insert it from "TB1"
the query I am doing is:
SELECT id, name from TB1, TB2 where id <> compid
what I get is 2 ouputs of Id 1, and 2, and 3 outputs from id 3. by using php:
for($i=0;$i <= mysql_num_rows($comp)-1; $i++)
{
echo mysql_result($comp, $i, 0)."<br>";
}
and I expected the ouput 3 but instead got this:
1
1
2
2
3
3
3
I understand its comparing all the rows within the table but is there a way to achieve what I am looking for?
Thanks for your time.
You are performing an implicit Cartesian JOIN which results in every row against every other row. You need to specify what attribute JOINs the two tables.
Using implicit syntax (not recommended):
SELECT id, name
FROM TB1, TB2
WHERE id <> compid
AND TB1.Name = TB2.property <-- Column join
Using explicit syntax:
SELECT id, name
FROM TB1
JOIN TB2
ON TB2.property = TB1.Name <-- Column join
WHERE id <> compid
To accomplish your goal you would need something along the lines of:
SELECT TB1.id, TB1.name
FROM TB1
LEFT JOIN TB2
ON TB2.property = TB1.Name
WHERE TB2.compid IS NULL
See it in action
It's best practice to always alias the columns you select to prevent ambiguity.
To select it you can do:
SELECT *
FROM TB1
WHERE id NOT IN (
SELECT compid
FROM TB2
);

Joining two tables but the join key is in a query string

I want to join these two table but the join key of the second table is in a query string,
page table,
page_id url
1 a
2 c
3 d
system table,
system_id query
1 page_id=1&content=on&image=on
2 type=post&page_id=2&content=on
as you can see that page_id is part of the query string in system table.
so how can I join them like the standard joining table method below?
SELECT*
FROM page AS p
LEFT JOIN system AS s
ON p.page_id = s.page_id
EDIT:
I def can change the system table into something like this,
system_id page_id query
1 1 page_id=1&content=on&image=on
2 2 type=post&page_id=2&content=on
3 NULL type=page
But the reason why I don't want to do this is that the page_id is no need for many certain records. I don't want make a column with too many null.
I would definitely create columns for page_id,content, image and type (and get them indexed). Then the database would be much lighter and would work much faster.
Joining two tables without the common field and data type, is fundamentally wrong IMO.
I will suggest that you extract the page_id and insert it in the database and use a normal join to accomplish what you are searching for.
SO making the columns like
+------------+-----------+---------+
| system_id | page_id | query |
------------------------------------
Here is a snippet with which you are extract the page_id.
$query = 'page_id=1&content=on&image=on';
$queryParts = explode('&', $query);
$params = array();
foreach ($queryParts as $param) {
$item = explode('=', $param);
$params[$item[0]] = $item[1];
}
$page_id = $parems['page_id'];
Then you can go on with the insert and use simple join statement to solve your problem in a proper way.
Update:
Since you are able to change the schema to a feasible one. You dont need to worry about some rows having empty rows on this.
I guess you wanted something like this (MSSQL!):
DECLARE #query VARCHAR(50)
DECLARE #Lenght INT
DECLARE #PageID INT
SET #query = '4kkhknmnkpage_id=231&content=on&image=on'
SET #Lenght = PATINDEX('%&%', substring(#query,PATINDEX('%page_id=%', #query),50)) - 9
SET #PageID = CAST(SUBSTRING(#query,PATINDEX('%page_id=%', #query) + 8,#Lenght) AS INT)
SELECT #PageID -- you can do as you please now :)
OR:
SELECT*
FROM page AS p
LEFT JOIN (SELECT CAST(SUBSTRING(query,PATINDEX('%page_id=%', query) + 8,(PATINDEX('%&%', substring(query,PATINDEX('%page_id=%', query),50)) - 9)) AS INT) AS page_id
FROM system) AS s
ON p.page_id = s.page_id
-- Do as you please again :)
I guess what you really wanted was something like this (MYSQL!):
SET #query := '4kkhknmnkpage_id=231&content=on&image=on';
SET #Lenght := POSITION('&' IN (SUBSTR(#query,POSITION('page_id=' IN #query),50))) - 9;
SET #PageID := CAST(SUBSTR(#query,POSITION('page_id=' IN #query) + 8,#Lenght) AS SIGNED );
SELECT #PageID
OR
SELECT*
FROM page AS p
LEFT JOIN (SELECT CAST(SUBSTR(query,POSITION('page_id=' IN query) + 8,(POSITION('&' IN (SUBSTR(query,POSITION('page_id=' IN query),50))) - 9)) AS SIGNED) AS pageID
FROM system) AS s
ON p.page_id = s.pageID

Categories