asp.net sql order by certain value - asp.net

hi i have an sql statement that returns rows from a table in descending order, the column i am ordering by is requestStatus. the requestStatus can be 3 values pending, approved and rejected . i would like to alter the sql if possible to order by pending then approved and then rejected. my sql statement is below. i am using asp.net razor view engine. can anyone point me in the right direction ?
var dbCommand2 = "SELECT * FROM LeaveRequests WHERE email = #0 ORDER BY WHERE requestStatus DESC";
var rows1 = db.Query(dbCommand2, theUserName);

Use CASE in your SELECT statement:
SELECT *, CASE requestStatus
WHEN 'pending' THEN 0
WHEN 'approved' THEN 1
WHEN 'rejected' THEN 2
END AS requestStatusOrder
FROM LeaveRequests
WHERE email = #0
ORDER BY requestStatusOrder

Related

ORA-01427: single-row subquery returns more than one row when inserting multiple rows

I am trying to assign or give all permissions of a user to another given user, 13053 but facing this Oracle error, ORA-01427: single-row subquery returns more than one row and i know exactly which part of my SQL statement shown below is returning this error but failed to handle it because what i want to achieve is to give those multiple rows returned to the given user with an id of 13053.
My attempt
INSERT INTO userpermissions (
userid,permissionid
) VALUES (
13053,( SELECT permissionid
FROM userpermissions
WHERE userid = ( SELECT userid
FROM users
WHERE username = '200376'
)
)
);
Any help ?
Thanks in advance.
A rewrite ought to do the trick:
INSERT INTO USERPERMISSIONS(
USERID,
PERMISSIONID
)
SELECT 13053 AS USERID,
p.PERMISSIONID
FROM USERPERMISSIONS p
WHERE p.userid = (SELECT userid FROM users WHERE username = '200376');
The problem with the original insert is that you are using single-row insert syntax when you are really trying to insert a set of rows.
Including the target userid as a literal is one way to make the set of rows look the way I am assuming you intend.

SELECT CASE - THEN - WHEN query throws an error [duplicate]

My code follows:
SELECT COUNT(_id) AS count FROM general WHERE _id = 1 CASE WHEN count > 0 THEN UPDATE general SET userGivenId = 'xxx' WHERE _id = 1 ELSE INSERT INTO general (userGivenId) VALUES ('xxx' ) END
With the error:
android.database.sqlite.SQLiteException: near "CASE": syntax error: , while compiling: SELECT COUNT(_id) AS count FROM general WHERE _id = 1 CASE WHEN count > 0 THEN UPDATE general SET userGivenId = 'xxx' WHERE _id = 1 ELSE INSERT INTO general (userGivenId) VALUES ('xxx' ) END
This is the shortest query I will use. Why I do this is because my other queries will have rows that needs to be updated but some may not be touched. Using replace will replace all the data (at least that is how it works for me on my Android phone). For instance my File class will have a filePath, but sometimes the response from the server will return null and I am only to update the File IF the server returns a new File.
Did I forget to write anything?
SQLite does not have any control logic because this would not make sense in an embedded database (there is no separate server machine/process whose asynchronous execution could improve performance).
CASE can be used only for expressions, not for entire commands.
Handle the control logic in your app:
Cursor c = db.rawQuery("SELECT 1 FROM general WHERE _id = 1", null);
if (c.moveToFirst())
db.execSQL("UPDATE general SET userGivenId = 'xxx' WHERE _id = 1");
else
db.execSQL("INSERT INTO general (userGivenId) VALUES ('xxx')");
For these particular commands, if you have a unique constraint on the _id column (and a primary key is constrained to be unique), you can use the INSERT OR REPLACE command:
INSERT OR REPLACE INTO general(_id, userGivenId) VALUES(1, 'xxx')

how to return something else when nothing is found?

My current query:
select timestamp from messagesTable
where partner_jid='" + lastUserJid + "' AND msg='.roll'
order by timestamp DESC LIMIT 1 OFFSET 1;
This works fine... unless the values don't exist in the database.
If values do not exist in database, then it should Select * messagesTable; or do nothing if possible.
Is there a way to add a check for that within the same query? It has to be the same query unfortunately because I need to execute things through adb shell. I've been trying things out with CASE but I do not really understand much about SQL.
You can just append a second query, with a WHERE filter that checks whether the first query did not return anything:
SELECT *
FROM (SELECT timestamp
FROM messagesTable
WHERE partner_jid = ?
AND msg = '.roll'
ORDER BY timestamp DESC
LIMIT 1 OFFSET 1)
UNION ALL
SELECT -1 -- or "timestamp FROM msgTab", or whatever
WHERE NOT EXISTS (SELECT timestamp
FROM messagesTable
WHERE partner_jid = ?
AND msg = '.roll');

razor sql error

I have this razor statement
sql = "SELECT * FROM CarBike" +
"Order By id OFFSET #0 ROWS FETCH NEXT #1 ROWS ;";
var result = db.Query(sql, offset, pageSize);
i am getting error
Incorrect syntax near the keyword 'By'.
Invalid usage of the option NEXT in the FETCH statement.
System.Data.SqlClient.SqlException: Incorrect syntax near the keyword 'By'.
Invalid usage of the option NEXT in the FETCH statement.
Please help me to correct this error
You need a space between CarBike and Order by
sql = "SELECT * FROM CarBike" +
" Order By id OFFSET #0 ROWS FETCH NEXT #1 ROWS ;";
NB: OFFSET/FETCH is SQL 2012+ only.
To achieve similar results in previous versions
select * from
(
select *, ROW_NUMBER() over (order by id) rn
from CarBike
) v
where rn between #0+1 and #0+#1
order by id

SQL Group By with a condition

Scenario: I need to create a report for the auditors for an ASP.Net application. I have a program that parses the XML of the web.config files in a directory for the authorization tag and creates a report providing which users have access to which folder in the site structure. The report is shown below.
UserName, Firstname, LastName, Directory, Roles, Access,
LastLoginDate
Problem: As you can see from the report some directories (the middle column with GISMO in it) show up twice, with both allow and deny for a user. I am wondering if there is a way to group the results in such a way that if there is a row that has allow for a directory then the deny's are not shown but otherwise they are.
Alternatively if this can be manipulated in VB.net/C# that is also an option. It comes back there and is pumped into an Excel spreadsheet.
Any help is appreciated. Thanks in advance.
Edit: I should have explained better. I still need the deny rows to show if the user isn't allowed in the directory. But if they are allowed then there is no point showing the deny rows.
This works on an Oracle database, so it should work or get you close on SQL Server as I know SQL Server
supports the main component of this, the CASE operation.
CREATE TABLE user_permissions (
user_role VARCHAR2(10) NOT NULL,
dir VARCHAR2(10) NOT NULL,
user_access VARCHAR2(5) NOT NULL
);
INSERT INTO user_permissions VALUES ('admin', 'dir1', 'allow');
INSERT INTO user_permissions VALUES ('admin', 'dir2', 'allow');
INSERT INTO user_permissions VALUES ('power', 'dir1', 'allow'); -- Allow and Deny dir1
INSERT INTO user_permissions VALUES ('power', 'dir1', 'deny');
INSERT INTO user_permissions VALUES ('power', 'dir2', 'deny');
COMMIT;
SELECT UNIQUE j.*
FROM (
SELECT user_role, dir,
MAX(CASE user_access WHEN 'allow' THEN 1 ELSE 0 END) allowFlag,
MAX(CASE user_access WHEN 'deny' THEN 1 ELSE 0 END) denyFlag
FROM user_permissions
GROUP BY user_role, dir
) t
JOIN user_permissions j ON (t.user_role = j.user_role AND t.dir = j.dir)
WHERE j.user_access = 'allow' OR (t.allowFlag = 0 and user_access = 'deny');
Results:
USER_ROLE DIR USER_ACCESS
---------- ---------- -----------
admin dir1 allow
admin dir2 allow
power dir1 allow
power dir2 deny
Basically, you use a pivot table to aggregate the multiple rows into a single row describing the attributes for the directory. Once you have the aggregated row, it's easy to compare the attributes you've declared to join up the rows that you want to display.
If you've got SQL Server 2005 or newer, you can use this:
with cte as (
select ROW_NUMBER() OVER (partition by username, directory order by access) as row, *
from report
)
select *
from cte
where row = 1
In the partition clause, put in whatever makes a "group" unique.
Reference:
http://msdn.microsoft.com/en-us/library/ms190766.aspx
http://msdn.microsoft.com/en-us/library/ms186734.aspx
Something like this should work but this assumes that your paths were not entered such as /directory/directory/, /directory/Directory/, directory/directory/default.aspx, etc. Your best bet would be to parse the data and remove duplicates at the .NET process level you've created, since parsing at that stage is usually easier.
select derived.*,
case when exists
(select top 1 1 from table_name as t2 where t2.username = derived.username and t2.directory=derived.directory and t2.access = 'allow') then 1 else 0 end as is_allowed,
case when exists
(select top 1 1 from table_name as t2 where t2.username = derived.username and t2.directory=derived.directory and t2.access = 'deny') then 1 else 0 end as is_denied,
from
(
select distinct t.username, t.firstname, t.lastname, t.directory
from table_name as t
) as derived
SELECT UserName, Firstname, LastName, Directory, Roles, Access, LastLoginDate
FROM Report R
WHERE Access = 'allow'
OR ( Access = 'deny'
AND NOT EXISTS
( SELECT *
FROM Report R2
WHERE R2.Directory = R.Directory
AND R2.UserName = R.UserName
AND R2.Roles = R.Roles
)
)
Based on your comments, this line should be removed, so only (UserName, Directory) combination is checked:
AND R2.Roles = R.Roles

Resources