Mysql not working correctly with and - mysql

i have the SQL statement:
SELECT `id`, `un`, `last_active`
FROM `users`
WHERE (`company_id` = :company_id
AND `un` LIKE :un
AND `id` != :id
AND `id` != :id)
ORDER BY id DESC
LIMIT 1
But this doesn't work correctly because i suspect that the repetitive component id is not being tested correctly.
So how can i have a sql statement with id!=1 AND id!=7

Related

improve mysql select query with order by option

I have following table with around 10 million records.
and using following query to retrieve data, but it is taking more than 4, 5 seconds to hand over the response.
Is any way to improve query...?
CREATE TABLE `master` (
`organizationName` varchar(200) NOT NULL DEFAULT '',
`organizationNameQuery` varchar(200) DEFAULT NULL,
`organizationLinkedinHandle` varchar(200) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`organizationDomain` varchar(110) NOT NULL DEFAULT '',
`source` varchar(10) NOT NULL DEFAULT '',
`modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY `master_inx` (`organizationName`(80),`organizationDomain`(80),`organizationLinkedinHandle`(80),`organizationNameQuery`(80),`source`),
KEY `organizationDomain` (`organizationDomain`),
KEY `domainWithModified` (`organizationDomain`,`modified`),
KEY `modifiedInx` (`modified`)
);
Query:
SELECT *
FROM (SELECT *
FROM Organizations.master
where ( ( organizationDomain like 'linkedin.com'
|| organizationNameQuery = 'linkedin.com')
and source like 'MY_SOURCE') ) M
ORDER BY M.modified DESC limit 1;
1 row in set (4.69 sec)
UPDATE
I found by breaking OR operator i am getting result faster.
For example:
SELECT *
FROM (SELECT *
FROM Organizations.master
where ( ( organizationDomain like 'linkedin.com')
and source like 'MY_SOURCE') ) M
ORDER BY M.modified DESC limit 1;
1 row in set (0.00 sec)
SELECT *
FROM (SELECT *
FROM Organizations.master
where ( (organizationNameQuery = 'linkedin.com')
and source like 'MY_SOURCE') ) M
ORDER BY M.modified DESC limit 1;
1 row in set (0.00 sec)
Use OR, not || in that context.
The performance villain is OR. Turn the OR into UNION:
( SELECT *
FROM Organizations.master
WHERE organizationDomain = 'linkedin.com'
AND source = 'MY_SOURCE'
ORDER BY modified DESC limit 1
) UNION ALL
( SELECT *
FROM Organizations.master
WHERE organizationNameQuery = 'linkedin.com'
AND source = 'MY_SOURCE'
ORDER BY modified DESC limit 1
}
ORDER BY modified DESC LIMIT 1;
Notes:
This formulation is likely to take about 0.00s to run.
The ORDER BY and LIMIT shows up 3 times.
If you need OFFSET, things get a little tricky.
Change back to LIKE if you allow users to enter wildcards.
A leading wildcard would not be efficient.
UNION ALL is faster than UNION (aka UNION DISTINCT).
It needs two new composite indexes; the order of the 2 columns is not critical:
INDEX(organizationDomain, source),
INDEX(organizationNameQuery, source)
As I checked the query I think you can remove the like operator and use =.
SELECT * FROM (
SELECT * FROM Organizations.master
where ( (organizationDomain = 'linkedin.com' ||
organizationNameQuery = 'linkedin.com')
and source = 'MY_SOURCE')
) M
ORDER BY M.modified DESC limit 1

How to fetch rows with prefered where clause, but also with a fallback?

I have a query (transaction) like this for fetching items from a table. I have a where clause of confirmed = '1', but would like to fallback to ignoring that where clause when no rows are found with the clause.
How can I do this in MySQL Server?
START TRANSACTION;
SELECT #id := `id`,`item`
FROM `queue_items`
WHERE `processed_at` IS NULL AND `completed_at` IS NULL AND confirmed = '1' ORDER BY `id` ASC
LIMIT 1
FOR UPDATE;
UPDATE `queue_items` SET `processed_at` = #processedAt, `worker_id` = #workerId WHERE `id` = #id;
COMMIT;
You could use a conditional sort:
SELECT #id := `id`, `item`
FROM `queue_items`
WHERE `processed_at` IS NULL AND `completed_at` IS NULL
ORDER BY (confirmed = 1) DESC, `id`
LIMIT 1

How to sort search results to display the first user with picture and after the others in MySQL

I have a problem with grouping and sorting.
(
SELECT
`subdomain` AS `id`,`name`,`lastname`,IF(`category` NOT LIKE '',`category`,0) AS `category`,`level`,`image`,`description` AS `summary`, '1' AS `type`
FROM
`user_professionals`
WHERE `keywords`='%{$keywords}%' AND `active`='1' AND `search`='1' AND
NULLIF(CONCAT(`name`, `lastname`), '') IS NOT NULL AND NULLIF(`description`, '') IS NOT NULL AND NULLIF(`category`, '') IS NOT NULL
GROUP BY `image`, `id`
ORDER BY `image` DESC
)
UNION
(
SELECT
`id`,`name`,`lastname`,IF(`category` NOT LIKE '',`category`,0) AS `category`,`level`,`image`,`summary`, '2' AS `type`
FROM
`users_amateurs`
WHERE `keywords`='%{$keywords}%' AND
`on_hold`='0' AND (`level`='2' OR `level`='3') AND `register`='1' AND `banned`='0'
AND
NULLIF(CONCAT(`name`, `lastname`), '') IS NOT NULL AND NULLIF(`summary`, '') IS NOT NULL AND NULLIF(`category`, '') IS NOT NULL
GROUP BY `image`, `id`
ORDER BY `image` DESC
)
LIMIT 100
PROBLEM:
Searching must be in two separate tables at the same time what should give a combined result in one query. Sorting and grouping needs to go in the following order:
Professional Users with images
Professional Users without images
Amateur Users with images
Amateur Users without images
This query works very well but the problem is sorting.
Thanks!

select last row only if a where condition is met

I have a column for messages and I am trying to figure out how I should display messages in "sent" folder.
I run the following query:
SELECT
`text`,
`created`
FROM
`messages`
WHERE
`status` = 1
ORDER BY `created` DESC
LIMIT 1
I want to introduce a condition so that result is returned only when the last row with status = 1 also has user_from = $user (If the last row has user_to = $user, then nothing should be returned).
What should my query be?
you can use a subquery
select `text`, `created` from T1
( SELECT
`text`,
`created`
FROM
`messages`
WHERE
`status` = 1
ORDER BY `created` DESC
LIMIT 1) T1
where `user_from` = $user and `user_to` != $user
If I understand your question correctly, do you want to do this:
SELECT
`text`,
`created`
FROM
`messages`
WHERE
`status` = 1
AND `user_from` = $user
AND `user_to` != $user
ORDER BY `created` DESC
LIMIT 1
Of course you need to replace $user with your string, or use a prepared statement to insert the variable into the query.
Select the latest message with status=1 and then use it as a nested query and check your conditions to output this one row result or not:
select `text`, `created`
from
(
SELECT
`text`,
`created`,
user_from,
user_to
FROM
`messages`
WHERE
`status` = 1
ORDER BY `created` DESC
LIMIT 1
) t
where (user_from = $user)
and (not (user_to = $user))

Every derived table must have its own alias - error from combination descending MySQL

I want to order one mysql table by two strtotime timestamps from two different columns. I've got the following mysql command:
SELECT * FROM (
(SELECT '1' AS `table`, `vid_req_timestamp` AS `timestamp`, `title` FROM `movies` WHERE `vid_req` = '1')
UNION
(SELECT '2' AS `table`, `ost_req_timestamp` AS `timestamp`, `title` FROM `movies` WHERE `ost_req` = '1')
)
ORDER BY `timestamp` DESC
This gives me an error:
#1248 - Every derived table must have its own alias
I want to combine vid_req_timestamp and ost_req_timestamp and make those descending. And it's important to know where the timestamp came from (somehow).
In this case, the derived table that requires an alias is the one that you are SELECTing * from.
Indentation helps make that clearer.
SELECT * FROM
(
(SELECT '1' AS `table`, `vid_req_timestamp` AS `timestamp`, `title` FROM `movies` WHERE `vid_req` = '1')
UNION
(SELECT '2' AS `table`, `ost_req_timestamp` AS `timestamp`, `title` FROM `movies` WHERE `ost_req` = '1')
) AS `some_table_name_lol_this_is_an_alias`
ORDER BY `timestamp` DESC