Mysql multiple AND and one OR - mysql

This is my query
SELECT time FROM logs WHERE (pstatus!=\"6\" OR ptype!=\"7\") AND uid=\"$id\" AND project=\"$pid\" GROUP BY project;
I wanna get only values(time) which ignores rows that has pstatus=6 or ptype=7.
What am i doing wrong here as it currently prints all values.

Have you tried using single quotes? Like
SELECT time FROM logs WHERE pstatus!='6' AND ptype!='7'
AND uid='$id' AND project='$pid' GROUP BY project;
Also, if you want to exclude rows where "pstatus=6 or ptype=7" then the negated form must use AND.

Related

Combine multiple rows into one JSON object/array from single MySQL query

I am trying to combine two rows of generated json within mysql, my current code outputs two rows (first is user id, second is the time) I want to combine them into one string. I've explored the use of GROUP CONCAT, JSON_MERGE (and JSON_MERGE_PRESERVE) and also JSON_OBJECTAGG. For further info, I am using MYSQL8.
Current output:
unavailability
{"59745190": "1400"}
{"59745190": "1200"}
My MySQL Script:
SELECT JSON_OBJECT(`appointment_with`, TIME_FORMAT(`appointment_datetime`,'%H%i')) as `unavailability`
FROM `appointments`
WHERE `appointment_with` = '59745190'
AND (DATE(`appointment_datetime`) = '2022-03-30' AND `appointment_confirmed` = 1)
Thank you in advance.

Not the same result between SqLite and MariaDb SELECT

I have 2 tables on Debian server, rides and steps.
From a Xamarin app I get data from this server (Refit, Newtonsoft Json and SQLite-net PCL packages) to populate local tables.
When I use this query on mariadb:
SELECT 1_steps.*
FROM 1_rides, 1_steps
WHERE 1_rides.id=1_steps.ride_id
AND 1_rides.start=1
GROUP BY 1_rides.id
I got correct results (first step of each ride, then it starts with 1)
But when use equivalent for SqLite:
SELECT Steps.*
FROM Rides,Steps
WHERE Rides.Id=Steps.RideId
AND Rides.Start=1
GROUP BY Rides.Id
In the result, I get the last step of each (same) ride!
Whether on mariadb or sqlite, each table has a primary key (id field).
I checked, the data is sent, received and saved in the same order.
Simply added in mobile app with:
foreach (var step in await App.RestClient.getSteps())
if (dbCon.InsertOrReplace(step) != 1)
....
I tried adding ORDER BY Rides.Id but that does not change anything.
You are relying on something that is not allowed by strict SQL standards: whenever you have a group by clause, the fields in the select clause must either appear in the group by clause as well, or must be aggregations (e.g. min, count), or must be functionally dependent on the group by fields.
In your case those conditions are not met and so if the DB engine allows this, it will have to decide which value to pick within a same group: the first, the last, or still something else.
The way to deal with this, is to be explicit what you want to get in such a case, by specifying an aggregation:
SELECT 1_steps.id,
min(1_steps.step),
max(1_steps.whatever),
avg(1_steps.some_number),
FROM 1_rides
INNER JOIN 1_steps
ON 1_rides.id=1_steps.ride_id
WHERE 1_rides.start=1
GROUP BY 1_rides.id
You did not specify the fields of your table, but the idea should be clear: list the fields separately (not *), and apply the type of aggregation to them you need.
Alternative
If you are not interested in aggregating anything, but just want one particular record from steps per ride, then don't use group by, but specify the condition that filters exactly that one record from steps:
SELECT 1_steps.*
FROM 1_rides
INNER JOIN 1_steps
ON 1_rides.id=1_steps.ride_id
WHERE 1_rides.start=1
AND 1_steps.step = 1
ORDER BY 1_rides.id
Note the condition 1_steps.step = 1: you'll have to decide what that condition should be of course.

SUM(IF(COND,EXPR,NULL)) and IF(COND, SUM(EXPR),NULL)

I'm working of generating sql request by parsing Excel-like formulas.
So for a given formula, I get this request :
SELECT IF(COL1='Y', SUM(EXPR),NULL)
FROM Table
I don't get the results I want. If I manually rewrite the request like this it works :
SELECT SUM(IF(COL1='Y', EXPR, NULL))
FROM Table
Also, the first request produces the right value if I add a GROUP BY statement, for COL1='Y' row :
SELECT IF(COL1='Y', SUM(EXPR),NULL)
FROM Table
GROUP BY COL1
Is there a way to keep the first syntax IF(COND, SUM(EXPR), NULL) and slightly edit it to make it works without a GROUP BY statement ?
You have to use GROUP BY since you are using SUM - otherwise SQL engine is not able to tell how do you want to summarize the column.
Alternatively you could summarize this column only:
SELECT SUM(EXPR)
FROM Table
WHERE COL1='Y'
But then you would have to run separate query for each such column, read: not recommended for performance reasons.

nested "select " query in mysql

hi i am executing nested "select" query in mysql .
the query is
SELECT `btitle` FROM `backlog` WHERE `bid` in (SELECT `abacklog_id` FROM `asprint` WHERE `aid`=184 )
I am not getting expected answer by the above query. If I execute:
SELECT abacklog_id FROM asprint WHERE aid=184
separately
I will get abacklog_id as 42,43,44,45;
So if again I execute:
SELECT `btitle` FROM `backlog` WHERE `bid` in(42,43,44,45)
I will get btitle as scrum1 scrum2 scrum3 msoffice
But if I combine those queries I will get only scrum1 remaining 3 atitle will not get.
You Can Try As Like Following...
SELECT `age_backlog`.`ab_title` FROM `age_backlog` LEFT JOIN `age_sprint` ON `age_backlog`.`ab_id` = `age_sprint`.`as_backlog_id` WHERE `age_sprint`.`as_id` = 184
By using this query you will get result with loop . You will be able to get all result with same by place with comma separated by using IMPLODE function ..
May it will be helpful for you... If you get any error , Please inform me...
What you did is to store comma separated values in age_sprint.as_backlog_id, right?
Your query actually becomes
SELECT `ab_title` FROM `age_backlog` WHERE `ab_id` IN ('42,43,44,45')
Note the ' in the IN() function. You don't get separate numbers, you get one string.
Now, when you do
SELECT CAST('42,43,44,45' AS SIGNED)
which basically is the implicit cast MySQL does, the result is 42. That's why you just get scrum1 as result.
You can search for dozens of answers to this problem here on SO.
You should never ever store comma separated values in a database. It violates the first normal form. In most cases databases are in third normal form or BCNF or even higher. Lower normal forms are just used in some special cases to get the most performance, usually for reporting issues. Not for actually working with data. You want 1 row for every as_backlog_id.
Again, your primary goal should be to get a better database design, not to write some crazy functions to get each comma separated number out of the field.

MySQL using table columns in function to create alias to be used in sorting

It sounds more complicated than it actually is. Here is what I'm trying to do within the SELECT part:
SELECT TIMESTAMPADD(
UCASE(
SUBSTRING(offset_unit,1,CHAR_LENGTH(offset_unit)-1)
),1,'2003-01-02') as offset_date
offset_unit is a VARCHAR column in the database. It contains one of the following: "Hours","Minutes".
offset is an INT.
I am trying to convert the offset_unit to uppercase, after I have removed the last character ('s') so I can have a proper interval (MINUTE, HOUR...) so I can get a date that I can use in sorting afterwards, but MySQL keeps throwing an error. I have tested each step by adding one function at a time, and it only fails after I add TIMESTAMPADD. If I enter MINUTE manually then it works.
Any way to get this working?
Additional info: I am running this in CakePHP 1.3, in a find, within the 'fields' array, but that shouldn't be important.
this can be easily achived by using CASE WHEN clause as:
SELECT (CASE
WHEN offset_unit = 'HOURS'
THEN TIMESTAMPADD(HOUR,`offset`,'2003-01-02')
WHEN offset_unit = 'MINUTES'
THEN TIMESTAMPADD(MINUTE,`offset`,'2003-01-02')
END) AS offset_date
FROM my_table;
SEE SQLFIDDLE DEMO HERE
It doesn't work because TIMESTAMPADD does not take a string as the first argument, but a unit keyword, for example MINUTE. My guess is that you need to do this in two steps, first get the unit and then construct a query with the correct keyword.