I have request from my MySQL table. It looks like below:
SELECT s . * , if( v.ip IS NULL , 0, 1 ) AS voted, v.vote
FROM `emvc4_records` s
LEFT JOIN `emvc4_records_votes` v ON ( s.id = v.record_id
AND v.day = CURRENT_DATE
AND v.ip = '2130706433' )
WHERE 1 =1
AND `category` =2
AND `caption` LIKE '%My%'
OR `description` LIKE '%My%'
ORDER BY `rating` DESC
LIMIT 0 , 25
I get this result:
id category category_name caption description created postby votes_up votes_down rating status have_voted vote
5 1 My second idea My second idea 2013-06-04 00:00:00 102 2 0 2 0 0 NULL
7 2 My first question My first question 2013-06-04 00:00:00 102 2 0 2 0 0 NULL
9 2 My second My second question 2013-06-04 00:00:00 102 1 0 1 0 0 NULL
My question: In my sql query I have: "AND category =2". So why I get record id=5 (it has category= 1) in my output?
Thanks!
The conditions in the WHERE clause are not properly organized. Add parentheses to group the conditions that you want. I guess LIKE '%My%' should be grouped.
SELECT s . *
, if( v.ip IS NULL , 0, 1 ) AS voted
, v.vote
FROM `emvc4_records` s
LEFT JOIN `emvc4_records_votes` v ON ( s.id = v.record_id
AND v.day = CURRENT_DATE
AND v.ip = '2130706433' )
WHERE 1 = 1
AND `category` = 2
AND (`caption` LIKE '%My%' OR `description` LIKE '%My%')
ORDER BY `rating` DESC
LIMIT 0 , 25
I don't why you added 1 = 1, but you can remove that.
Your query should be look like:
...............
`category` =2
AND (`caption` LIKE '%My%' OR `description` LIKE '%My%')
.................
Related
SELECT pa.prid,pa.prodid,pa.prva, ps.psna,ps.psnamid,ps.psval
FROM ( SELECT pid,prodid,count(prodid) as prid ,
sum(prval) as prva
FROM prodarpa
WHERE fcl = 1 GROUP BY prodid
UNION SELECT pid,prodid,count(prodid) as prid ,
sum(prval) as prva
FROM prodarpb
WHERE fcl = 1 GROUP BY prodid ) AS pa
LEFT JOIN (SELECT psid,psnamid,count(psnamid) as psna,SUM(psvalue) as psval
FROM prosection GROUP BY psnamid ) AS ps
ON ( pa.pid = ps.psid )
Hence i want result as below :
pa.prid | pa.prodid | pa.prva | ps.psna | ps.psnamid | ps.psval
193 3 300 193 2 499
200 5 100 0 0 0
0 0 0 201 8 300
163 10 678 163 5 453
What i mean is if pa.prid value is not in ps.psna then it should show 0 value in each column of ps table and same on another way
but its not happening
Without data to work from this is guesswork.
SELECT
pa.prid
, pa.prodid
, pa.prva
, ps.psna
, ps.psnamid
, ps.psval
FROM (
SELECT
pid
, prodid
, COUNT(prodid) AS prid
, SUM(prval) AS prva
FROM (
SELECT
pid
, prodid
, prval
FROM prodarpa
WHERE fcl = 1
UNION ALL
SELECT
pid
, prodid
, prval
FROM prodarpb
WHERE fcl = 1
) AS s
GROUP BY
pid
, prodid
) AS pa
LEFT JOIN (
SELECT
psid
, psnamid
, COUNT(psnamid) AS psna
, SUM(psvalue) AS psval
FROM prosection
GROUP BY
psid
, psnamid
) AS ps ON (pa.pid = ps.psid)
Take care when using group by that you always specify ALL non-aggregating columns. MySQL does provide for a syntax where this isn't required - however the results of using that syntax are not reliable, and the syntax is only allowed if ONLY_FULL_GROUP_BY is enabled.
see: https://dev.mysql.com/doc/refman/5.0/en/group-by-handling.html
I have table for student attendance like below:
id | Present | date
1 | 1
1 | 0
1 | 1
1 | 1
1 | 0
Now I want to get the total days he is present via single query. Is it possible?
Below is the way I used to get the student present/absent count:
select count(*) from table where present =1
select count(*) from table where present =0
But I think can I get both from one query instead of two.
select sum(present = 1) as present1,
sum(present = 0) as present0
from table
You can use the following query:
select (select count(*) from table where present=1) as "present"
, (select count(*) from table where present=0) as "absent";
Try this its working fine :
SELECT SUM( present =1 ) AS present, SUM( present =0 ) AS absent
FROM details
WHERE id =1
Screenshot :
Try this :
For all student with group by
select id,present,absent from
(
select id,sum(case when present = 1 then 1 else 0 end) as present,
sum(case when present = 0 then 1 else 0 end) as absent
from table_name
group by id
) as absen
if you want to show only one student, just add where clause in the end like this :
select id,present,absent from
(
select id,sum(case when present = 1 then 1 else 0 end) as present,
sum(case when present = 0 then 1 else 0 end) as absent
from table_name
group by id
) as absen
where id = '1'
Hope this help you..
I have a scenario that a query who will work like select records based on status = 1 with highly number of records found in database.
suppose i want to select artists who have max number of status = 1 with their names fetch from other table.
another problem is my query is repetiting records.
my query:
SELECT order.status,
order.artist_id,
web_user.uFname,
web_user.uLname,
web_user.uID
FROM `order`
INNER JOIN `web_user`
ON web_user.uID = order.artist_id
HAVING order.status = '1'
my record set i am getting:
status artistid uFname uLaname uID
1 14 Pitbull Armando 14
1 14 Pitbull Armando 14
1 13 Enrique Iglesias 13
1 15 Robyn Rihanna 15
1 15 Robyn Rihanna 15
1 15 Robyn Rihanna 15
i simple want:
downloadtimes artistid uFname uLaname uID
2 14 Pitbull Armando 14
1 13 Enrique Iglesias 13
3 15 Robyn Rihanna 15
please enhanced my query.
You can use COUNT()
SELECT
COUNT(*) AS downloadtimes ,
order.artist_id,
web_user.uFname,
web_user.uLname,
web_user.uID
FROM `order`
INNER JOIN `web_user` ON web_user.uID = order.artist_id
WHERE order.status = '1'
GROUP BY order.artist_id
you should use the count
like:
COUNT(*) AS downloadtimes
you should just add the like you full code:
SELECT
COUNT(*) AS downloadtimes ,
order.artist_id,
web_user.uFname,
web_user.uLname,
web_user.uID
FROM `order`
INNER JOIN `web_user` ON web_user.uID = order.artist_id
WHERE order.status = '1'
GROUP BY order.artist_id
and refer this following link:
SQL COUNT
id title cat lang
6101 AAba 1 1
6102 AAad 4 2
6103 AAaf 4 2
6104 AAa 1 1
6105 AAtar 4 2
6106 AAao 1 1
6107 ABya 4 2
6108 ABar 4 2
6109 ACar 1 2
6110 BCad 3 1
6111 CCas 4 1
6112 DCas 4 2
6113 GCaz 2 2
6114 FCaew 2 2
6115 FCaw3 4 2
6116 FCa3 1 1
6117 FCa4 4 2
6118 FCa5 2 1
6119 FCa6 4 2 --- last id
Table news, id is primary key, title - is title field,
cat - there are four types of categories of news, lang - language code 1 or 2.
I want to achieve following:
1) Case Edit news - id is available - for example 6111, lang is 1, cat is 4
I want to collect these id and titles:
6119
6117
6115
6112
6109
6105
6103
6102
which are the opposite language - lang is 2, the same category cat is 4 and
within range of 4 (or n) id before and after given id 6111
also ordered desc
2) Case Add news - id is not available, or after insert in php is mysql_insert_id()
the same functionality - last 10 id with the same cat = 4 and the opposite lang = 2
So far I have tried this:
for case 1) php snippet:
$id = 6111;
$lang = 1;
$tip = 4;
$sql = "SELECT id, title
FROM pubs
WHERE id BETWEEN ".($id-4)." AND ".($id+4). " AND
tip = ".$tip." AND
lang <> ".$lang."
ORDER BY id DESC ";
BUT this gets 4 id before and after the id, not from the collection of id I need .
for case 2)
$sql = "SELECT id, title
FROM news
WHERE cat = 4 AND
lang <> 1
ORDER BY id DESC LIMIT 10";
This seem to be working, but may be I'm wrong.
Is there any way to achieve Case 1 this with php and mysql?
Better way for case 2?
Given that you only have the $id, this horrible looking beast is the best I can come up with. I'm fairly sure there's a tidier way to do it, but I think this will work (FIXED)
$id = 6111;
$query = "
SELECT `id`, `title`
FROM `news`
WHERE `id` IN (
SELECT * FROM (
SELECT `id`
FROM `news`
WHERE `cat` = (
SELECT `cat`
FROM `news`
WHERE `id` = ".$id."
) AND `lang` != (
SELECT `lang`
FROM `news`
WHERE `id` = ".$id."
) AND `id` < ".$id."
ORDER BY `id` DESC
LIMIT 4
) `lower`
) OR `id` IN (
SELECT * FROM (
SELECT `id`
FROM `news`
WHERE `cat` = (
SELECT `cat`
FROM `news`
WHERE `id` = ".$id."
) AND `lang` != (
SELECT `lang`
FROM `news`
WHERE `id` = ".$id."
) AND `id` > ".$id."
ORDER BY `id` ASC
LIMIT 4
) `upper`
)
ORDER BY `id` DESC
";
Something like this might work:
$sql = "SELECT id, title FROM pubs
WHERE tip = ".$tip." AND lang <> ".$lang."
ORDER BY id DESC
LIMIT ".($id-4).",".($id+4);
There may be a more elegant solution, but this gets the job done.
My issue is that I need to paginate data from this query:
function search($search_term, $limit, $offset)
{
$id = $this->auth->get_user_id();
$query = $this->db->query("
SELECT user_id,
first_name,
cars_name,
cars_id
FROM user_profiles
LEFT JOIN cars
ON cars.id_fk = user_id
WHERE user_id NOT LIKE '$id'
AND activated = 1
AND banned = 0
AND first_name LIKE '%$search_term%'
ORDER BY first_name ASC
");
$search_data = array();
foreach ($query->result() as $row) {
$search_data[$row->user_id]['name'] = $row->first_name;
$search_data[$row->user_id]['cars'][$row->cars_id] = array(
'cars_name' => $row->cars_name);
}
return $search_data;
}
A sample data table / query response would be:
1 JOE HONDA 123
1 JOE TOYOTA 124
2 MAC VW 125
2 MAC HONDA 126
2 MAC TESLA 127
3 STU SUBARU 128
3 STU KIA 129
-----------
Page 1
-----------
1 JOE HONDA 123
TOYOTA 124
2 MAC VW 125
HONDA 126
------------
Page 2
------------
3 STU SUBARU 128
KIA 129
If I enter a limit and offset at the end of MySQL query
...
LIMIT $limit
OFFSET $offset;
");
the limit and offset are applied to the total number of rows, not the the number of rows grouped by user.
I've tried using GROUP BY but was unable to make it work.
My goal is to make the query as above but LIMIT and OFFSET the query by a number of rows that counts users, not all rows.
Any ideas?
I don't see a way to do this in one query. My solution would be to get the count of unique ID's using a group by query with the same parameters:
SELECT COUNT(1) AS uid_count
FROM user_profiles
LEFT JOIN cars
ON cars.id_fk = user_id
GROUP BY user_profiles.user_id
WHERE user_id NOT LIKE '$id'
AND activated = 1
AND banned = 0
AND first_name LIKE '%$search_term%'
Then fetch the uid_countmysql_num_rows and use that to calculate pagination variables for the above query.
The solution really is to use a GROUP BY clause:
SELECT SQL_CALC_FOUND_ROWS
user_id,
first_name,
cars_name,
cars_id
FROM user_profiles
LEFT JOIN cars
ON cars.id_fk = user_id
WHERE user_id NOT LIKE '$id'
AND activated = 1
AND banned = 0
AND first_name LIKE '%$search_term%'
GROUP BY user_id
ORDER BY first_name ASC
LIMIT 100
The order is important. GROUP BY first, then ORDER BY, and then OFFSET/LIMIT.
Notice the SQL_CALC_FOUND_ROWS up there? After the query has executed, if you want to get the total row count (including those who aren't returned because of the LIMIT clause), just use:
SELECT FOUND_ROWS() AS `count`
And fetch the count column.
However, like you said, the rows will collapse and you will lose some cars_name and cars_id values.
Another solution is to use GROUP_CONCAT, then split it in PHP:
SELECT
user_id,
first_name,
GROUP_CONCAT(cars_name SEPARATOR ','),
GROUP_CONCAT(cars_id SEPARATOR ','),
FROM user_profiles
LEFT JOIN cars
ON cars.id_fk = user_id
WHERE user_id NOT LIKE '$id'
AND activated = 1
AND banned = 0
AND first_name LIKE '%$search_term%'
ORDER BY first_name ASC
LIMIT 100
This would give you something like:
1 JOE HONDA,TOYOTA 123,124
2 MAC VW,HONDA,TESLA 125,126,127
3 STU SUBARU,KIA 128,129
If you want to get a list like this
Page 1
----------------------
1 JOE HONDA 123
1 JOE TOYOTA 124
Page 2
----------------------
2 MAC VW 125
2 MAC HONDA 126
2 MAC TESLA 127
Page 3
----------------------
3 STU SUBARU 128
3 STU KIA 129
Forget about limit, do this instead:
A - First retrieve a list of user id's and insert that into a temp table
CREATE TEMPORARY TABLE `test`.`temp_user_ids` (
`id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` INTEGER UNSIGNED NOT NULL,
PRIMARY KEY (`id`)
)
ENGINE = MEMORY
B - Next insert the relavant user_id's into the table.
INSERT INTO temp_user_ids
SELECT null, user_id
FROM user_profiles
LEFT JOIN cars
ON cars.id_fk = user_id
WHERE user_id NOT LIKE '$id'
AND activated = 1
AND banned = 0
AND first_name LIKE '%$search_term%'
ORDER BY user_id DESC /*insert in reverse order !*/
The lowest user_id is the last_insert_id in the temptable, and the temp_table
items are in sequential order.
C - Set the SQL #var #current_id to the last_insert_id in the temp_table.
SELECT #current_id:= LAST_INSERT_ID()
D - Next select relevant rows from the table, using only the user_id you want.
SELECT count(*) as row_count,
up.user_id,
first_name,
group_concat(cars_name) as car_names,
group_concat(cars_id) as car_ids,
FROM user_profiles up
LEFT JOIN cars
ON cars.id_fk = up.user_id
INNER JOIN temp_user_ids t
ON (t.user_id = up.user_id)
WHERE t.id = #current_id
GROUP BY up.user_id
ORDER BY cars.id
E - Now lower the #current_id
SELECT #current_id:= #current_id - 1;
F - And repeat step D and E until there's no more rows to be had.
The first field row_count tells you the number of rows aggregated in the fields
car_names and car_ids. You can separate these fields by using php's explode.