mysqli query for multiple cases with coditions - mysql

Need to select data if condition first true then check user id exist, if condition not true then check condition two then check user id not exist
Technologies used: Codigniter - Mysqli
SELECT *
FROM `tablename`
WHERE `user_id` = '1'
OR `user_id` IN('62', '63', '58', '6', '50', '19', '2', '17', '7', '3')
AND `user_id` NOT IN('35')
OR (CASE WHEN except_friends = 1 THEN FIND_IN_SET('1', friends_list), FALSE END CASE WHEN selected_friends = 1 THEN NOT FIND_IN_SET('1', friends_list), FALSE END) ORDER BY `id` desc
Mysql syntax error

I think there is syntax error in your query. try this one
SELECT * FROM tablename
WHERE user_id = '1'
OR user_id IN('62', '63', '58', '6', '50', '19', '2', '17', '7', '3')
AND user_id NOT IN('35')
OR
(CASE
WHEN except_friends = 1
THEN NOT FIND_IN_SET('1', friends_list)
WHEN selected_friends = 1
THEN NOT FIND_IN_SET('1', friends_list)
END) ORDER BY id desc

Related

how to reorder row position using select statement in mysql

SELECT * FROM TJU.`group`;
group_id, name
'1', 'x'
'2', 'y'
'3', 'z'
'4', 'a'
'5', 'b'
I want re arrange position of data in mysql using select statement
expect output
group_id, name
'1', 'x'
'2', 'y'
'3', 'z'
'5', 'b'
'4', 'a'
please suggest me how to implement this so that I can get record like this
try a query like this:
select * from TJU.`group` order by FIELD(group_id,1,2,3,5,4(;;
to change id without name
select
find_in_set (id,'1,2,3,5,4'),`name`
from TJU.`group`

SQL Get most frequent value from a column based on a condition

This query
SELECT
PlayerID, HeroTypeID, HeroTypeIDCount, Wins / (Losses + Wins) AS WinRate, Wins, Losses
FROM (
SELECT E.PlayerID AS PlayerID,
FK_HeroTypeID AS HeroTypeID,
COUNT(FK_HeroTypeID) AS HeroTypeIDCount,
SUM(CASE WHEN D.Result = 'LOSS' THEN 1 ELSE 0 END) AS Losses,
SUM(CASE WHEN D.Result = 'WIN' THEN 1 ELSE 0 END) AS Wins
FROM GamePlayerDetail D
JOIN Player E
ON D.FK_PlayerID = E.PlayerID
JOIN Game I
ON D.FK_GameID = I.GameID
WHERE PlayedDate BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND CURDATE()
GROUP BY E.PlayerID, FK_HeroTypeID
) AS T
ORDER BY PlayerID
produces the following result:
# PlayerID, HeroTypeID, HeroTypeIDCount, WinRate, Wins, Losses
'1', '11', '1', '1.0000', '1', '0'
'1', '13', '3', '0.3333', '1', '2'
'1', '24', '5', '0.8000', '4', '1'
'1', '27', '1', '1.0000', '1', '0'
'2', '28', '1', '0.0000', '0', '1'
'2', '6', '1', '0.0000', '0', '1'
'2', '30', '1', '0.0000', '0', '1'
'2', '7', '1', '1.0000', '1', '0'
What I'd like to do is get the most frequent FK_HeroTypeID (which is also highest value of HeroTypeIDCount) per PlayerID, but in case of ties, the highest winrate should take precedence. Here's an example of what I'd like to get:
PlayerID, HeroTypeID, HeroTypeIDCount, WinRate, Wins, Losses
1, 24, 5, 0.8000, 4, 1
2, 7, 1, 1.0000, 1, 0
How should you write a query like this?
Edit:
Ok, here's a simple Create/Insert table for the produced result.
http://sqlfiddle.com/#!9/d644a
SELECT playerid
, herotypeid
, herotypeidcount
, winrate
, wins
, losses
FROM
( SELECT *
, CASE WHEN #prev=playerid THEN #i:=#i+1 ELSE #i:=1 END rank
, #prev:=playerid prev
FROM table1
, (SELECT #prev:=null,#i:=0) vars
ORDER
BY herotypeidcount DESC
, winrate DESC
) x
WHERE rank = 1;
Here's a 'hack' solution. It works, but really shouldn't be relied upon...
SELECT *
FROM
( SELECT *
FROM table1
ORDER
BY herotypeidcount DESC
, winrate DESC
) x
GROUP
BY playerid

SQL query to show top x records with evenly distributed values

I have a database of contacts at companies. Multiple contacts per company in different departments. Each company has turnover and industry data attached to it.
I need to write a query that shows the top 10 most recently added contacts (unix timestamp) but i don't want it to be all Marketing contacts (even if the top 10 are), i would like to look at the top 100 instead and get 10 contacts out that are from different departments. So instead of the top 10 being all marketing, there might be 2 marketing, 2 I.T, 2 HR, 2 Personnel.
So my query basically is this:
SELECT DISTINCT `surname`, `job_title`, `company_name`
FROM (`company_database`)
WHERE `employee_code` IN ('6', '7', '8', '9', '10', '11', '12', '13')
AND `turnover_code` IN ('5', '6', '7', '8')
AND `contact_code` IN ('16', '17', '26', '27', '9', '10', '30', '31', '23', '24', '12', '13') AND `industry_code` NOT IN ('22', '17', '35', '36') LIMIT 10
But that simply returns a unique row. What i need is one contact per company and no more than 1 contact_code type. I also only want 10 rows returned, but obviously to get this 1 per contact code per row, the query will need to look at more than 10.
Is this possible in just a query? Or should i do something programatically to apply the logic needed to whittle down the results of a query.
you can work with a temporary table using the myisam engine and a trick.
If you create the following temporary table:
create table tmp_company_sequence
( surname varchar(255)
,job_title varchar(255)
,company_name varchar(255)
,date_added date
,contact_code int
,counter int auto_increment
,primary key (contact_code,counter)
);
Now
insert into `tmp_company_sequence`( `surname`, `job_title`, `company_name`,`contact_code`,`date_added`)
SELECT DISTINCT `surname`, `job_title`, `company_name`,`contact_code`,`date_added`
FROM (`company_database`)
WHERE `employee_code` IN ('6', '7', '8', '9', '10', '11', '12', '13')
AND `turnover_code` IN ('5', '6', '7', '8')
AND `contact_code` IN ('16', '17', '26', '27', '9', '10', '30', '31', '23', '24', '12', '13') AND `industry_code` NOT IN ('22', '17', '35', '36')
order by contact_code, added_date desc;
Your temporary table will now hold all the contacts with a counter. The counter is increased for every contact of the same contact_code. SO the newest contact with a certain contact code will have counter = 1, the next recent will have counter = 2 and so on.
You can now do a
select *
from tmp_company_sequence
order by counter asc, date_added desc
limit 10;
This will give you a list of the latest contacts added over all contact_codes.
Edit:
I just realised this could be done with a single query, but it is even more ugly:
SELECT `surname`
, `job_title`
, `company_name`
, `contact_code`
FROM(
SELECT
`surname`
, `job_title`
, `company_name`
, `contact_code`
, `date_added`
, IF(contact_code = #prev_contact_code,#i:=#i+1,#i:=1) AS counter
, #prev_contact_code = contact_code
FROM
(`company_database`)
,(SELECT #i := 1)
WHERE `employee_code` IN ('6', '7', '8', '9', '10', '11', '12', '13')
AND `turnover_code` IN ('5', '6', '7', '8')
AND `contact_code` IN (
'16'
, '17'
, '26'
, '27'
, '9'
, '10'
, '30'
, '31'
, '23'
, '24'
, '12'
, '13'
)
AND `industry_code` NOT IN ('22', '17', '35', '36')
ORDER BY contact_code
, added_date DESC) sub
WHERE counter = 1
ORDER BY added_date DESC
LIMIT 10;
This does basically the same as the option with the temporary table, but it creates the counter in the fly by storing data from the previous column in global variables. It is messy but can be used within a single query.

MySQL SUM and CASE possible on DISTINCTROW?

I have this query :
SELECT
p.name,
COUNT(DISTINCT t.keyTask) AS totalTasksCount,
SUM(DISTINCT CASE WHEN t.keyPriority = 24 AND (t.keyState = 16 OR t.keyState = 17) THEN 1 ELSE 0 END) AS highPriorityTasksCount,
SUM(DISTINCT CASE WHEN t.keyState = 16 OR t.keyState = 17 THEN 1 ELSE 0 END) AS activesTasksCount,
SUM(DISTINCT t.estimatedDuration) AS estimatedDuration,
SUM(TIMESTAMPDIFF(SECOND,wp.start,wp.end)) * 1000 AS workedDuration
FROM projects_projects p
LEFT JOIN projects_tasks t
ON p.keyProject = t.keyProject
LEFT JOIN projects_workPeriods wp
ON wp.keyTask = t.keyTask
LEFT JOIN common_organizations o
ON o.keyOrganization = p.keyOrganization
LEFT JOIN common_users uc
ON uc.keyUser = p.keyUserCreator
LEFT JOIN common_users uu
ON uu.keyUser = p.keyUserUpdater
GROUP BY
p.keyProject
ORDER BY
highPriorityTasksCount DESC,
activesTasksCount DESC,
p.updated DESC,
p.name;
But the result fields highPriorityTasksCount and activesTasksCount returns 0 or 1 which is normal with this query. I was wondering if there is any way to make DISTINCTROW work on row and not on case result value for these fields without subquery ?
Current result :
p.name,
totalTasksCount,
highPriorityTasksCount,
activesTasksCount,
estimatedDuration,
workedDuration
'Project 1', '4', '1', '1', '14400000', '15300000'
'Project 2', '48', '1', '1', '84600000', '503100000'
'Project 3', '6', '1', '1', '108000000', NULL
'Project 4', '4', '1', '1', '25200000', '30600000'
'Project 5', '5', '1', '1', '226800000', '39600000'
'Project 6', '2', '0', '1', NULL, '10800000'
'Project 7', '9', '0', '1', NULL, '36900000'
Expected result :
'Project 1', '4', '1', '1', '14400000', '15300000'
'Project 2', '48','20', '2', '84600000', '503100000'
'Project 3', '6', '1', '1', '108000000', NULL
'Project 4', '4', '4', '2', '25200000', '30600000'
'Project 5', '5', '5', '1', '226800000', '39600000'
'Project 6', '2', '0', '1', NULL, '10800000'
'Project 7', '9', '0', '1', NULL, '36900000'
EDIT :
Modified query with subqueries since there is no way, help about optimization would be appreciated, this one is working :
SELECT
p.name,
COUNT(DISTINCT t.keyTask) AS totalTasksCount,
/* OLD SUM(DISTINCT CASE WHEN t.keyPriority = 24 AND (t.keyState = 16 OR t.keyState = 17) THEN 1 ELSE 0 END) AS highPriorityTasksCount, */
(
SELECT
SUM(CASE WHEN st.keyPriority = 24 AND (st.keyState = 16 OR st.keyState = 17) THEN 1 ELSE 0 END)
FROM projects_tasks st
WHERE
st.keyProject = p.keyProject
) AS highPriorityTasksCount,
/* OLD SUM(DISTINCT CASE WHEN t.keyState = 16 OR t.keyState = 17 THEN 1 ELSE 0 END) AS activesTasksCount, */
(
SELECT
SUM(CASE WHEN st.keyState = 16 OR st.keyState = 17 THEN 1 ELSE 0 END)
FROM projects_tasks st
WHERE
st.keyProject = p.keyProject
) AS activesTasksCount,
SUM(t.estimatedDuration) AS estimatedDuration,
SUM(TIMESTAMPDIFF(SECOND,wp.start,wp.end)) * 1000 AS workedDuration
FROM projects_projects p
LEFT JOIN projects_tasks t
ON p.keyProject = t.keyProject
LEFT JOIN projects_workPeriods wp
ON wp.keyTask = t.keyTask
LEFT JOIN common_organizations o
ON o.keyOrganization = p.keyOrganization
LEFT JOIN common_users uc
ON uc.keyUser = p.keyUserCreator
LEFT JOIN common_users uu
ON uu.keyUser = p.keyUserUpdater
GROUP BY
p.keyProject
ORDER BY
highPriorityTasksCount DESC,
activesTasksCount DESC,
p.updated DESC,
p.name;
without subquery.
No, you will have to use a subquery, or there's something I don't know about MySQL.

Conditional MySQL Column

Table: qa_selltypes
selltype_code, selltype_name
'1', 'unit'
'2', 'pound'
'3', 'box'
'4', 'gallon'
Table: qa_items
item_code, item_name, selltype_code, item_price
'1', 'PS2 Keyboard', '1', '10.45'
'2', 'Screws', '3', '15.02'
'3', 'Oil', '2', '30.00'
I need to refill a grid that contains four fields (unit, stall, pound, gallon) establishing item_price according to the relation to the field of selltype_code, one example: The rest set them to 0
DGV:
item_code, item_name, unit, box, pound, gallon
'1', 'PS2 Keyboard', '10.45', '0', '0', '0'
'2', 'Screws', '0', '0', '15.02', '0'
'3', 'Oil', '0', '30.00', '0', '0'
select i.item_code, i.item_name,
case when q.selltype_name = 'unit' then i.item_price else 0 end as unit,
case when q.selltype_name = 'box' then i.item_price else 0 end as box,
case when q.selltype_name = 'pound' then i.item_price else 0 end as pound,
case when q.selltype_name = 'gallon' then i.item_price else 0 end as gallon
from qa_items i
inner join qa_selltypes q on i.selltype_code = q.selltype_code
You can use a case. Example:
select case when some_column = 'abc'
then 'hello'
else 'good bye'
end as conditional_column
from your_table