Check multiple columns for validity - mysql

Is this a legitimate/good way of checking multiple column values in a row (in order to send to the user the appropriate feedback)?
select
(date_expires < now()) as expired,
(date_deleted is not null) as active
from sometable where row='foo';
It seems awfully convenient to me (this way I can make one query and conditionally alert the user to what exactly is wrong with the row they are trying to access), but I actually haven't seen it very much so I'm worried there is a big downside that I'm not seeing. Thanks!

Your method works, it's just going to give back separate columns. If you want one column to hold the result, then it's some case statement fun.
select
case when date_expires < now() then 'Inactive'
else 'active'
end as status
from sometable where row='foo';
That would give you status with inactive/active as it's two values. I just went with else active, you can put in a series of when this condition then 'this value' if you wanted.

Related

How to assign value of field based on other rows fields values in MySql

I have an Asterisk cdr database with rows representing every "call" (it's actually multiple rows per call depending on if it's inbound, outbound, local) executed inside my office.
I have 3 extensions (200, 201, 202) so for every inbound call asterisk generates 3 rows with the same 'uniqueid' and a 'disposition' indicating whether said extension answered or not a said call.
I utilize this data to generate a Call History listview for a small desktop program running on every desk and I need to show only the calls of a given extension and FROM HERE stems my question:
I should show every inbound call of my extension BUT if a call disposition is 'NO ANSWER' BUT STILL someone else answered that specific call i shoudn't show the call since it is not actually missed; to say it in other words, I should show a call missed only if EVERY extension missed it (has NO ANSWER disposition).
I thought of flagging a row with a bool field conditioned on whether or not there is at least one row with the same 'uniqueid' that has disposition 'ANSWER'. I added the column 'isToDiscard' but I don't now how to go on; maybe triggers could be used but i couldn't do it.
Am I approaching the problem in a meaningful way? I kinda did this in the backend but this flag or approach whould make everything easier.
We can identify the non-answered calls with a window function:
select *
from (
select c.*,
max(disposition = 'ANSWERED') over(partition by uniqueid) as was_answered
from cdr c
) c
where was_answered = 0
Expression disposition = 'ANSWER' returns 1 if the value matches, else 0 : taking the maximum of that value over a group of calls (as identify by a partition rows sharing the same uniqueid) tells us if the call was answered by any desk. We can the use that information to filter.
If you want to filter the resultset for a specific desk (extension), then you can simply add the filter to the outer query.

SQL/mysql - how to display two columns with different value from 1 table

I am trying to make a query for approval of documents, where the result display the name and signature with date. How can I get the date for two people approving the document?
Select Uname
case when stepcode=1 then 'approver1' end as 'name of person'
case when stepcode=1 then 'approver1' end as ' date of signed noted'
case when stepcode=2 then 'approver2' end as 'date of signed approved'
from table
I tried this, but only one result showed up. Only the name, signature and date of the first approval displayed.
We can only answer this by making some assumptions:
the field stepcode denotes what stage of the sign off process the record is at
value of 1 means noted and value 2 means approved. A value of 0 means nothing has happened yet
approver1 and approver 2 are NULL if the action has not yet taken place
If all of the above is true, then there should be no requirement to have a CASE statement for the fields... just including the fields within the SELECT statement will bring the values through if they have been completed.
Some validation of data might be required here though if you are not getting the results you are expecting. Running some rough counts for each of the steps and for where they have values in the approver fields would help to make sure your code is working. The following should give you something to work with:
SELECT
stepcode
COUNT(TableID) AS NumberAtStep
FROM table
GROUP BY stepcode
Using these counts, you can then run your statement without the CASE statements and run a manual count to ensure you are seeing the right number of records with the relevant populated columns for each step.
Further information will be required to delve into your problem further however

Tell from Which table MySQL COALESCE returned the value

i have the following part of query:
SUM(COALESCE(user_a, user_b)) AS income_adsense
Now, i have a html table in my web app where i present the data from this query.
problem is i want to mark data in one color if answer is from col user_a and different color if answer is from user_b col.
is there a way to achieve that in my query itself? (some sort of flag maybe?)
.
right now the only solution i have is to return all col's and work with the data on the client side but i am wondering if there's a cleaner/best practice solution.
guess it's worth mentioning i don't want to change the table structure.
Well, to make sense of the data I would do something like:
CASE
WHEN SUM(user_a) > SUM(user_b)
THEN 'User_A'
ELSE 'User_B'
END [Most of the data comes from]
You could also have two separate SUM() columns to make sense of this and compare the sum of values in your application.
SUM(user_a) [User_A Score Weight]
, SUM(user_b) [User_B Score Weight]

Advanced discount system in stored procedure

I am making a stored procedure for monthly sales. In the stored procedure we have a Discount. This discount can be fetched from three different tables. If the discount is not in id.rabatt, it should fetch from dp.rabatt, if its not there, it should fetch from ds.rabatt. So the first two ones can be empty, while the last one always has a discount..
Im having big trouble designing the WHEN part of the procedure. Please take a look and help me on the way if you have time:
CASE (
when
Isnull(id.rabatt, Isnull(u.rabatt, id.rabatt)) then..
when
Isnull(dp.rabatt, Isnull(x.rabatt, dp.rabatt)) then..
when
Isnull(ds.rabatt, Isnull(y.rabatt, ds.rabatt)) then..
end)
AS 'Discount',
The reason i have to use Isnull is that inside each Discount table, i also have two different discounts, one that lasts forever(2999) and one that have a selected period. Like i show here:
LEFT OUTER JOIN discount AS id
ON id.identifiers = isa.identifiers
AND id.store = BV.name
AND id.from_date <= isa.sales_date
AND id.to_date >= isa.sales_date
AND id.to_date < '2999-01-01'
LEFT OUTER JOIN discount AS u
ON u.identifiers = isa.identifiers
AND u.to_date = '2999-01-01'
The two others tables are designed in similar ways.
You can use the coalesce function in a similar way that you are using the IsNull function. There are some subtle differences between IsNull and Coalesce, but the significant difference that would benefit your code is that you can have multiple parameters without needing to nest it.
Your code: Isnull(id.rabatt, Isnull(u.rabatt, id.rabatt))
Is the same as: Coalesce(id.rabatt, u.rabatt, id.rabatt)
Next... there are 2 general forms for case/when.
Case (Some Condition)
When (Value 1) Then ...
When (Value 2) Then ...
Else (Default Value)
End
Or
Case When (SomeCondition = Value1) Then ...
When (SomeCondition = Value2) Then ...
Else DefaultValue
End
Looking at your code snippet, it appears as though you are using the second form, but you don't have a comparison operator in the when part. I think you want something like this...
CASE When Coalesce(id.rabatt, u.rabatt, id.rabatt) Is Not NULL then..
When Coalesce(dp.rabatt, x.rabatt, id.rabatt) Is Not NULL then..
When Coalesce(ds.rabatt, y.rabatt, id.rabatt) Is Not NULL then..
Else (Put a default value here)
end AS [Discount]

How to determine if a field/column is affected by an UPDATE statement

Hello everyone and thank you for your answers and comments.
I have a table with several fields, among which are version, last_modified and modified_by
I'm writting a trigger to:
increase version by 1 after every/any update,
set last_modified to the current timestamp,
set the id of the user who made the latest changes into modified_by, and
prevent the programmer from ignoring/forgetting to set modified_by = userid in the UPDATE statement by raising a signal (in such case).
How can I achieve this?
I tried checking if isnull(NEW.modified_by), but then realized that NEW.modified_by takes the same value as OLD.modified_by if it wasn't affected. Also, checking if NEW.modified_by equals OLD.modified_by doesn't quite make it, since it could be a user modifiyng a record previously modified by himself.
Is there a way to determine which fields where affected by the UPDATE statement? Or if a particular field (modified_by) was affected?
I cannot find anything that will allow you to inspect the incoming information to see which fields are being affected. While I know you are trying to stop this issue at the trigger level, it might be prudent to require all table writes to go through a stored procedure. That way you could require the user field.
If that isn't a possibility, I think you might need to get tricky. For example, you could require that the user_id be written to two fields (create an extra column that is blank for this purpose). Then, compare the user_id in the dummy column to the one you are updating. Once you figure out if you need to modify the user_id or not, blank out the dummy column again. It isn't pretty, but it would get the job done.
I had a similar issue. I have a table with a tinyint column named isDirty, and wanted to set it to 1 when the row is updated, and clear it to 0 when the row has been "cleaned".
The problem is, the combination of NEW and OLD with values of 0 and 1 didn't give me enough values to solve my problem. So instead, I made a "rule" that when the column was updated to a value of 100, it was set to the clean value of "0", anything else set it to "1". The reason this works is that this column will only ever have one of 2 values, 0 or 1, so you can use 100 (or any value of your choice) as the "flag" that indicates that it is clean.
I know that it sounds a little backwards to set it to a non-zero value to get back to 0, but that's the direction I chose and it works. Here's what that trigger looks like:
CREATE TRIGGER calls_update BEFORE UPDATE ON `calls`
FOR EACH ROW
BEGIN
IF ( NEW.isDirty = 100 ) THEN
SET NEW.isDirty = 0;
ELSE
SET NEW.isDirty = 1;
END IF;
END
$$
As far as I know, your only option is to check each column's NEW value against the OLD.
SET `ColumnAChanged` = NEW.ColumnA <=> OLD.ColumnA;
SET `ColumnBChanged` = NEW.ColumnB <=> OLD.ColumnB;