This is kind of hard to headline, but given this statement:
SELECT DISCOUNT FROM people_discounts WHERE ID = ? AND PGROUP = ?
Let's assume I enter ID 5 and PGROUP 2. This row does not exist in the table (fetch returns false in the case of PHP and mysqli). In that case I want the row that would have been presented had the statement been:
SELECT DISCOUNT FROM people_discounts WHERE ID = ? AND PGROUP = 0
With ID still being 5, but PGROUP "fallen back" to 0 instead, which let's assume always exists.
Is this possible with some kind of IF, CASE or maybe some other keyword that I'm not aware of?
I know this can of course be accomplished by running a second statement in the case of no rows, but that's not what I'm trying to do.
presuming the query should only ever return a single row
select discount from people_discount
where id = ? and (pgroup = ? or pgroup = 0)
order by pgroup desc
limit 1;
If limit seems "impure" you could use other tricks.
This might be more portable though it assumes that discount is never negative:
select abs(max(case when proup <> 0 then discount else -discount end))
from people_discount
where id = ? and pgroup in (?, 0)
group by id
Not every platform has a top/limit/fetch option. And some people object to non-set-based queries. I'm simply offering a hack of sorts with those people in mind or at least as an exercise in thinking about problems in a different way.
The idea is just to assume there cannot be a negative discount and to use that end of the number scale to temporarily "store" the fallback discount for pgroup 0. MAX() accomplishes the equivalent of sorting and limiting by favoring the positive value when both are present. ABS() restores the sign of the result.
Related
I am looking for a (sub-)query and/or If statement in a MYSQL query. After Googling and searching, I THINK it should be possible with a CASE statement, but I am not sure.
My Questions are:
1: is it possible at all?
2: If it is: Could someone point me in the right direction on how to achieve this?
ISSUE:
I have a table with PRODUCTS. Each PRODUCT can have a
-'in_stock' value of 0 or 1 (in stock NO or YES).
-'status' with possible value of 'NULL' or 'DELETED'.
A product that has the status 'DELETED' can NOT be ordered, UNLESS in is in stock.
QUESTION
Is it possible to apply (some kind of) IF statement in a SQL query? Something like:
SELECT
*
FROM
products
WHERE
CASE in_stock = 0
THEN (AND status != 'DELETED')
ELSE ()
I hope someone can help me out. Thanks in advance!
Consider:
SELECT *
FROM products
WHERE
(in_stock = 0 AND status <> 'DELETED') OR
in_stock > 0;
You can use AND and OR in a WHERE clause. The following query gives you all products that are either in stock or have not been deleted (or both):
SELECT *
FROM products
WHERE in_stock = 1 OR status <> 'DELETED';
Another way of writing the same:
SELECT *
FROM products
WHERE NOT (in_stock = 0 AND status = 'DELETED');
You can have many conditions that you combine with AND, OR, and parentheses.
I have a MySQL query that includes <> in it. I don't know the exact usage of it.
SELECT * FROM table_laef WHERE id = ? AND genre_type <> 'LIVE'
P.S.: Im sorry for this basic syntax, since I have searched for this on Google. All they give is about <=>. Thanks anyway, guys!
<> is Standard SQL and stands for not equal or !=.
<> means not equal to, != also means not equal to.
Documentation
<> means NOT EQUAL TO, != also means NOT EQUAL TO. It's just another syntactic sugar. both <> and != are same.
The below two examples are doing the same thing. Query publisher table to bring results which are NOT EQUAL TO <> != USA.
SELECT pub_name,country,pub_city,estd FROM publisher WHERE country <> "USA";
SELECT pub_name,country,pub_city,estd FROM publisher WHERE country != "USA";
In MySQL, I use <> to preferentially place specific rows at the front of a sort request.
For instance, under the column topic, I have the classifications of 'Chair', 'Metabolomics', 'Proteomics', and 'Endocrine'. I always want to list any individual(s) with the topic 'Chair', first, and then list the other members in alphabetical order based on their topic and then their name_last.
I do this with:
SELECT scicom_list ORDER BY topic <> 'Chair',topic,name_last;
This outputs the rows in the order of:
Chair
Endocrine
Metabolomics
Proteomics
Notice that topic <> 'Chair' is used to select all the rows with 'Chair' first. It then sorts the rows where topic = Chair by name_last.*
*This is a bit counterintuitive since <> equals != based on other feedback in this post.
This syntax can also be used to prioritize multiple categories. For instance, if I want to have "Chair" and then "Vice Chair" listed before the rest of the topics, I use the following
SELECT scicom_list ORDER BY topic <> 'Chair',topic <> 'Vice Chair',topic,name_last;
This outputs the rows in the order of:
Chair
Vice Chair
Endocrine
Metabolomics
Proteomics
In MySQL, <> means Not Equal To, just like !=.
mysql> SELECT '.01' <> '0.01';
-> 1
mysql> SELECT .01 <> '0.01';
-> 0
mysql> SELECT 'zapp' <> 'zappp';
-> 1
see the docs for more info
<> is equal to != i.e, both are used to represent the NOT EQUAL operation. For instance, email <> '' and email != '' are same.
I know im late to the game but maybe this will help somebody...
this is not true even though everyone wrote it
<> is equal to !=
it actually is less than or greater than
the exception is with NULL
column <> 3 will not get null columns
column != 3 will get null columns
hope it helps
I have made a few relations to do with a banking database system.
this is my current code. The table has
SELECT COUNT(AccountType) AS Student_Total FROM Account
WHERE AccountType ='Student'
and SortCode = 00000001;
SELECT COUNT(AccountType) AS Student_Total FROM Account
WHERE AccountType ='Student'
and SortCode = 00000002;
SELECT COUNT(AccountType) AS Student_Total FROM Account
WHERE AccountType ='Student'
and SortCode = 00000003;
the rest of the code is a duplicate of this part with the next type of 'Account' and looping back through sortcode's 1-3 again.
I was wondering if there was a more elegant way of producing this. I need to count the number of student, current and saver accounts for each bank.
Or is there a way to combine lots of selects together to make a neat table?
That's what GROUP BY is for!
SELECT SortCode,COUNT(AccountType) AS Student_Total FROM Account
WHERE AccountType ='Student'
GROUP BY SortCode;
UPDATE:
You can also GROUP BY with multiple grouping fields:
SELECT SortCode,AccountType,COUNT(AccountType) AS Student_Total FROM Account
GROUP BY SortCode,AccountType;
You could also apply a PIVOT approach to this query to always return a single row and know the fixed-final columns of the result set. However, applying a group by allows for more flexibility of returned rows, especially if you have a large amount of individual things you are trying to tally up.
select
A.AccountType,
SUM( IF( A.SortCode = 1, 1, 0 )) as SortCode1Cnt,
SUM( IF( A.SortCode = 2, 1, 0 )) as SortCode2Cnt,
SUM( IF( A.SortCode = 3, 1, 0 )) as SortCode3Cnt
from
Account A
where
A.AccountType = 'Student'
AND A.SortCode IN ( 1, 2, 3 )
group by
A.AccountType
Note... it appears your sort code is a numeric as you have no quotes around indicating a character string. So, all the leading zeros are irrelevant. And if you were only doing based on a single Account Type, you don't even need the leading Account Type column and can remove the group by too.
Im making a table generator as a school project.
In MySQL I have 3 tables namely process,operation,score. Everything looked fine until i tested out my "ADD column" button in the web app.
Previous saved data should be read properly but also include the new column in the format, problem is the previous data queried does not include any values for the new table, so I intended it to return a score of 0 if no records were found, tried IFNULL & COALESCE but nothing happens(maybe im just using it wrong)
process - processID, processName
operation - operationID, operationName
score - scoreID, score, processID, operationID, scoreType (score
types are SELF,GL,FINAL)
ps = (PreparedStatement)dbconn.prepareStatement("SELECT score FROM score WHERE processID=? and operationID=? and type=?ORDER BY processid");
here's a pic of a small sample http://i50.tinypic.com/2yv3rf9.jpg
The reason that IFNULL doesn't work is that it only has an effect on values. A result set with no rows has no values, so it does nothing.
First, it's probably better to do this on the client than on the server. But if you have to do it on the server, there's a couple of approaches I can think of.
Try this:
SELECT IFNULL(SUM(score), 0) AS score
FROM score
WHERE processID=? and operationID=? and type=?
ORDER BY processid
The SUM ensures that exactly one row will be returned.
If you need to return multiple rows when the table contains multiple matching rows then you can use this (omitting the ORDER BY for simplicity):
SELECT score
FROM score
WHERE processID = ? and operationID = ? and type = ?
UNION ALL
SELECT 0
FROM (SELECT 0) T1
WHERE NOT EXISTS
(
SELECT *
FROM score
WHERE processID = ? and operationID = ? and type = ?
)
Is there way to realize this algorithm with mysql without 100500 queries and lots of resources?
if (exists %name% in table.name) {
num = 2;
while(exists %newname%+(num) in table.name) num++;
%name% = newname+(num);
}
Thanks
I don't know how much better you can do with a stored procedure in MySql, but you can definitely do better than 100500 queries:
SELECT name FROM table WHERE name LIKE 'somename%' ORDER BY name DESC LIMIT 1
At that point, you know that you can increment the number at the end of name and the result will be unused.
I 'm glossing over some fine print (this approach will never find and fill any "holes" in the naming scheme that may exist, and it's still not guaranteed that the name will be available due to race conditions), but in practice it can be made to work quite easily.
The simpliest way I can see of doing it is to create a table of sequential numbers
then cross join on to it....
SELECT a.name,b.id
FROM table a
WHERE a.name = 'somename'
CROSS JOIN atableofsequentialnumbers b
WHERE NOT EXISTS (SELECT 1 FROM table x WHERE x.name = CONCAT(a.name,b.id))
LIMIT 10
This will return the first 10 available numbers/names