update 1: here is my data looks like.
EmployeeId EmployeeName Active
12312 bob 0
23432 rob 1
32312 dan 0
43432 jan 1
.........................
.........................
UPDATE:
I am looking after something like this.
EmployeeId EmployeeName Active
12312 bob active
23432 rob pending
.........................
.........................
I am trying work around the following sql statement and its throwing me an error and not sure if this is the right way of doing...
//error:
Incorrect syntax near the keyword 'SET'.
declare #currentStatus nvarchar(50)
Select EmployeeId,EmployeeName,Active,
set #currentStatus = case when EmployeeId is not null and Active = 0 then "Active" else "Pending" end as Status
from EmployeeTable
I think you should try this:
SELECT EmployeeId, EmployeeName, CASE
WHEN (EmployeeId IS NOT NULL AND Active = 0) THEN 'Active' ELSE 'Pending'
END AS [Status]
FROM EmployeeTable
To get the results you show in your updated question, this is the only query you need. I have no idea why you think you need a local variable to hold the results of the case expression on each row.
SELECT
EmployeeId,
EmployeeName,
Active,
[Status] = CASE WHEN EmployeeId IS NOT NULL AND Active = 0
THEN 'Active'
ELSE 'Pending' END
FROM dbo.EmployeeTable;
EDIT updated with sample data provided in question:
DECLARE #e TABLE(EmployeeID INT, EmployeeName VARCHAR(32), Active BIT);
INSERT #e VALUES
(12312,'bob',0),
(23432,'rob',1),
(32312,'dan',0),
(43432,'jan',1);
SELECT
EmployeeId,
EmployeeName,
Active,
[Status] = CASE WHEN EmployeeId IS NOT NULL AND Active = 0
THEN 'Active'
ELSE 'Pending' END
FROM #e;
Results:
EmployeeId EmployeeName Active Status
12312 bob 0 Active
23432 rob 1 Pending
32312 dan 0 Active
43432 jan 1 Pending
Select EmployeeId,EmployeeName,Active,
case when EmployeeId is not null and Active = 0 then 'Active' else 'Pending' end as Status
from EmployeeTable
if you need to set the #CurrentStatus variable then you'll need to do that separately:
Set #currentStatus = case when EmployeeId is not null and Active = 0 then 'Active' else 'Pending' end
from EmployeeTable
Related
I am new to mysql, here i am trying to get data from database table.
select id,txnid,amount,status from txn_details;
With above query Getting data successfully but status column getting 0 or 1 or 2, but i want 0 as failed, 1 as success and 2 as not processed.
How to change my query?
You can use a case
select id, txnid, amount,
case when status = 0 then 'failed'
when status = 1 then 'success'
else 'not processed'
end as status
from txn_details;
We can use an expression in the SELECT list. It could be a searched CASE expression e.g.
SELECT CASE t.status
WHEN 0 THEN 'failed'
WHEN 1 THEN 'success'
WHEN 2 THEN 'not processed'
ELSE 'unknown'
END AS status_name
, t.status
, t.amount
, t.txnid
FROM txn_details t
This approach is ANSI-92 standards compliant, and will work in most relational databases.
There are some other MySQL specific alternatives, such as the ELT function ...
SELECT ELT(t.status+1,'failed','success','not processed') AS status_name
, t.status
, t.amount
, t.txnid
FROM txn_details t
https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_elt
If you prefer a central point of maintenance (ie you prefer not to recode all your queries when a new status comes along) you could create a status table and either use a join or sub query to get the values, alternatively you could create a function, for example
drop table if exists txn_details,txn_status;
create table txn_details(id int, txnid int, amount int , status int);
insert into txn_details values
(1,1,10,1),(2,1,10,2),(3,1,10,4);
create table txn_status (id int, statusval varchar(20));
insert into txn_status values
(1,'success'),(2,'not processed'), (3,'failed');
drop function if exists f;
delimiter $$
create function f(instatus int)
returns varchar(20)
begin
declare rval varchar(20);
return (select
case when instatus = 1 then 'success'
when instatus = 2 then 'not processed'
when instatus = 3 then 'failed'
else 'Unknown'
end
);
select t.*,coalesce(ts.statusval,'Unknown') status
from txn_details t
left join txn_status ts on ts.id = t.status;
select t.*,coalesce((select statusval from txn_status ts where ts.id = t.status),'Unknown') status
from txn_details t;
Note the use of coalesce in case a status is not found.
Both produce this result
+------+-------+--------+--------+---------------+
| id | txnid | amount | status | status |
+------+-------+--------+--------+---------------+
| 1 | 1 | 10 | 1 | success |
| 2 | 1 | 10 | 2 | not processed |
| 3 | 1 | 10 | 4 | Unknown |
+------+-------+--------+--------+---------------+
3 rows in set (0.00 sec)
Using the function like this
select t.*, f(status) as status
from txn_details t;
also produces the same result.
Of course using a status table or a function means you have to communicate their availability and enforce their use.
I would also consider the using a foreign key constraint in txn_details to cut down on the number of unknown values and put procedures in place to stop people adding new status codes at will without going through change control
The following query would work. It uses CASE ... END to determine and return values for the virtual column status.
SELECT id,txnid,amount,
CASE
WHEN status = 0 THEN 'failed'
WHEN status = 1 THEN 'success'
WHEN status= 2 THEN 'not processed'
END AS status
FROM txn_details;
I am working on this peculiar sql stored proc where the business case is as follows:
Business Case:
Table Specialties contains all the Specialties and there is a bit field for each record telling if it's Active or Inactive. We always display only the active records from that table in form of dropdown. Users may select a Specialty which can later on be deactivated. New requirement is to be able to pull that Inactive record along with all the active records in the result set.
Here's how I thought I should do this:
If no specialty is assigned to the person I am pulling up then the dropdown is going to be populated by all active records.
If there is a inactive specialty associated with the person I am pulling up then I send that specialtyID in stored proc as a parameter and return that inactive records along with active records to populate the dropdown.
Below is what I got so far:
So far if I dont pass in any specialtyId then I am returning active specialty records which is working. When I send in a specialtyId parameter then it just returns that one inactive record but not rest of the other active records. I need the rest of the active records too along with that one inactive record.
DECLARE #specialtyId INT = null;
BEGIN
IF isnull(#specialtyId,'')=''
BEGIN
SELECT SpecialtyID AS Id, Specialty AS Name
FROM dbo.Specialties
WHERE IsActive = 1
ORDER BY Specialty;
END
ELSE
BEGIN
SET #specialtyId = #specialtyId ;
SELECT s.SpecialtyID AS Id, s.Specialty AS Name
FROM dbo.Specialties s
WHERE specialtyId = #specialtyId
GROUP BY s.Specialty, s.SpecialtyID
HAVING (Specialty IS NOT NULL)
AND (max(SpecialtyID) IS NOT NULL)
ORDER BY Name;
END
END
It seems to me that this can be done with no IF whatsoever:
SELECT s.SpecialtyID AS Id,
s.Specialty AS Name
FROM dbo.Specialties s
WHERE specialtyID = #specialtyId
OR IsActive = 1;
You can do this all in the where clause. In the case below it checks to see if the #specId is pass in and selects only that ID or Inactive records OR if the #specId is 0 then just select the active records.
IF OBJECT_ID('tempdb..#tmptest') IS NOT NULL
DROP TABLE #tmptest
CREATE TABLE #tmptest
(
SpecialtyID INT IDENTITY(1,1) NOT NULL PRIMARY KEY
, SpecialtyName VARCHAR(50) NOT NULL
, IsActive BIT NOT NULL DEFAULT (0)
)
INSERT INTO #tmptest
VALUES
('Peditrician', 1)
, ('Rad Tech', 1)
, ('Surg Nurse', 1)
, ('Peds Nurse', 1)
, ('Cardio Doctor', 0)
, ('Cardio Nurse', 1)
, ('Test Doctor', 1)
DECLARE #SpecID INT = 0
SELECT *
FROM #tmptest
WHERE
(
(#SpecID > 0 AND (SpecialtyID = #SpecID OR IsActive = 0))
OR
(#SpecID = 0 AND IsActive = 1)
)
I have a table like this:
| id | address | name | oid | state | event_id | ctrl |
-------------------------------------------------------------------
| 1 | test_addr_1 | test_1 | 25.345.17 | 1 | 0 | 15 |
I need to get event_id while update data in row.
I want to do something like this:
If new name not equals with old name event_id = event_id + 1
If new oid not equals with old oid event_id = event_id + 2
If new state not equals with old state event_id = event_id + 4
If new ctrl bigger then old ctrl event_id = event_id + 8
# Params to procedure
PROCEDURE Write(IN pAddr VARCHAR(20), IN pName VARCHAR(20), IN pOid VARCHAR(20), IN pState TINYINT, IN pCtrl INT)
#procedure body
SET #ev = 0;
SELECT
CASE
WHEN name != pName THEN SET #ev = #ev + 1
WHEN oid != pOid THEN SET #ev = #ev + 2
WHEN state != pState THEN SET #ev = #ev + 4
WHEN ctrl > pCtrl THEN SET #ev = #ev + 8
END
FROM table1
UPDATE table1 SET ..... , event_id = #ev WHERE address = pAddr
How can I do it? Or will it be better to make it not with the help of SQL?
As already suggested, an audit trigger can be used here to ensure that changes from all sources are caught. However, I suggest two changes:
1) audit tables - use other tables to hold audit data, as these tables tend to grow and it is not recommended to mix operational and auditing data in the same structures (even in the same database)
2) use more friendly change flag - from your example, it seems that you are setting bits in an integer value. While this provides compact data (catch many changes within a single integer), it requires more convoluted operations to see when the name has changed for example. The audit table can simply have BIT(1) columns like nameChanged, oidChanged etc.
CREATE TRIGGER table1Audit BEFORE UPDATE ON <table1>
FOR EACH ROW BEGIN
SET #ev =
(CASE WHEN OLD.name != NEW.name THEN 1 ELSE 0 END) +
(CASE WHEN OLD.oid != NEW.oid THEN 2 ELSE 0 END) +
(CASE WHEN OLD.state != NEW.state THEN 4 ELSE 0 END) +
(CASE WHEN OLD.ctrl != NEW.ctrl THEN 8 ELSE 0 END)
-- INSERT INTO someaudittable
--'table1', #ev
END;
Solved! Thanks to #Alexei.
I wanted to know, why the row was added to the history table.
The result is:
CREATE TRIGGER SetReason BEFORE UPDATE ON <table1>
FOR EACH ROW BEGIN
SET NEW.event_id =
(CASE WHEN OLD.name != NEW.name THEN 1 ELSE 0 END) +
(CASE WHEN OLD.oid != NEW.oid THEN 2 ELSE 0 END) +
(CASE WHEN OLD.state != NEW.state THEN 4 ELSE 0 END) +
(CASE WHEN OLD.ctrl != NEW.ctrl THEN 8 ELSE 0 END)
END;
I'm creating a query wherein I would count how many awards does an applicant have. So far I have this:
SELECT
CASE WHEN Award1 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Award2 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Award3 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Award4 IS NOT NULL THEN 1 ELSE 0 END
as summedColumn
FROM resume, person
where E_Status = 'Applicant'
and person.ID_No like 'x' and resume.ID_No like 'x'
Table:Person Values
ID_No(Varchar, Primary) x
F_Name(Varchar) Fasa
L_Name(Varchar) Bel
M_Name(Varchar) Drake
Resume_ID(Varchar) res01
Table: Resume Value
Resume_ID(Varchar, Primary) res01
ID_No(Varchar) x
Award1(Varchar) Suma Cum Laude
Award2(Varchar) null
Award3(Varchar) null
Award4(Varchar) null
Past_Position1(Varchar) HR manager
Past_Position2(Varchar) null
Output of the query: 4
When I ran the code it returned a value of 4 but my Award2, Award3 and Award4 are all null. The code suppose to return a value of 1.
Here is the look of the table:
You didn't join your two tables, so it is making a cross join between Resume and Person tables.
Find the key which relates Person to Resume, and equals them together:
SELECT
CASE WHEN Award1 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Award2 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Award3 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Award4 IS NOT NULL THEN 1 ELSE 0 END
as summedColumn
FROM resume
INNER JOIN person
ON resume.Resume_ID = person.Resume_ID
where E_Status = 'Applicant'
and person.ID_No like 'x' and resume.ID_No like 'x'
Maybe you want to rethink your database structure.
How about creating an 1:n structure?
Table structure Person: ID, Name ...
Table Structure AwardRel: PersonID, AwardRel
Table Structure Awards: ID, AwardName, ...
With a 1:n structure like this, your query can be expressed as:
SELECT COUNT(*) FROM `AwardRel` WHERE `PersonID` = 1;
This query should return any number of awards Person 1 has ever obtained.
I have a "receipt Information Report". For instance
ID Name Date Createtor Payment Date
1 Bob 12.12.2012 bb 01.01.2013
2 Smith 15.01.2010 smt 15.02.2011
3 Peter 21.02.2011 ptr null
4 Sarah 18.06.2012 srh 23.07.2012
I want to add a parameter into this report like that;
List all the receipts(Then it will list the report above)
List all the receipts which have been created by Sarah
List all the receipt which have been paid.
List all the receipt which haven't been paid.
I have created the report without the parameter. How may I adjust these parameters into my report?
You could parameterize your query as follows:
IF #PAYMENTSTATUS = 'ALL'
BEGIN
SELECT ID, NAME, [DATE], CREATOR, PAYMENTDATE FROM RECEIPT
WHERE NAME = CASE #NAME WHEN 'ALL' THEN NAME ELSE #NAME END
END
IF #PAYMENTSTATUS = 'PAID'
BEGIN
SELECT ID, NAME, [DATE], CREATOR, PAYMENTDATE FROM RECEIPT
WHERE NAME = CASE #NAME WHEN 'ALL' THEN NAME ELSE #NAME END
AND PAYMENTDATE IS NOT NULL
END
IF #PAYMENTSTATUS = 'UNPAID'
BEGIN
SELECT ID, NAME, [DATE], CREATOR, PAYMENTDATE FROM RECEIPT
WHERE NAME = CASE #NAME WHEN 'ALL' THEN NAME ELSE #NAME END
AND PAYMENTDATE IS NULL
END
Really it could be simpler if not that I could not figure how to case a date column correctly in SQL where clause, then you would not need 3 if statements.
Next, you can use a different dataset, in parameter properties, get values from a query, to populate your #Name parameter e.g.
select 'ALL'
UNION
SELECT DISTINCT NAME FROM RECEIPT
Lastly, you can simply use available values for the #PAYMENTSTATUS parameter and specify values 'ALL', 'PAID', 'UNPAID'.