load row data based on the first filed in the row - asp.net

i have to develop new website for CAR Wash company , this company own three cleaning car which receive order from my system , max order per day for every car is 5 orders so i should add 5 green places beside every car in the the same car row . (ex) if car have two order so two fields with background yellow and other three fields in green background
I have two tables
Cars
Orders
Car table
ID CarName
1 Car1
2 Car2
3 Car3
Order table
ID ClientName Phone Date CarID
1 Jack 11111 22-7-2017 10:22:00 AM 2
2 Susan 22222 22-7-2017 01:30:00 PM 2
3 Hany 33333 22-7-2017 10:22:00 AM 3
4 Karim 44444 21-7-2017 08:22:00 AM 1
5 Halaa 55555 22-7-2017 05:22:00 PM 3
i want to select all orders for every car in one row per day based on selection of day from DATETIMEPICKER so i will select orders for 22-07
Cars Orders
car1 Empty Empty Empty Empty Empty
car2 Jack(111111) Susan(22222) Empty Empty Empty
car3 Hany(333333) HalaSusan(55555) Empty Empty Empty
So how can do it if i use GridView and what is the best query

The following should do the trick...
IF OBJECT_ID('tempdb..#Vehicle', 'U') IS NOT NULL
DROP TABLE #Vehicle;
GO
CREATE TABLE #Vehicle (
VehicleID INT NOT NULL PRIMARY KEY CLUSTERED,
VehicleName VARCHAR(10) NOT NULL
);
GO
INSERT #Vehicle (VehicleID, VehicleName) VALUES
(1, 'Car1'), (2, 'Car2'), (3, 'Car3');
GO
IF OBJECT_ID('tempdb..#Orders', 'U') IS NOT NULL
DROP TABLE #Orders;
GO
CREATE TABLE #Orders (
OrderID INT NOT NULL PRIMARY KEY CLUSTERED,
ClientName VARCHAR(15) NOT NULL,
PhoneNumber VARCHAR(10) NOT NULL,
ServiceDate DATETIME NOT NULL,
VehicleID INT NOT NULL -- create FK refference back to Vehicle.VehicleID)
);
GO
-- create an index to support the row_number() function...
-- The sort cost is greater than the difference between a seek & scan...
CREATE NONCLUSTERED INDEX ix_Orders_VehicleID_ServiceDate
ON #Orders (VehicleID, ServiceDate)
INCLUDE (ClientName, PhoneNumber);
GO
INSERT #Orders (OrderID, ClientName, PhoneNumber, ServiceDate, VehicleID) VALUES
(1, ' Jack ', '11111', '07-22-2017 10:22:00 AM', 2),
(2, ' Susan', '22222', '07-22-2017 01:30:00 PM', 2),
(3, ' Hany ', '33333', '07-22-2017 10:22:00 AM', 3),
(4, ' Karim', '44444', '07-21-2017 08:22:00 AM', 1),
(5, ' Halaa', '55555', '07-22-2017 05:22:00 PM', 3);
GO
--SELECT * FROM #Vehicle v;
--SELECT * FROM #Orders o;
--=======================================================================
DECLARE #WorkDate DATE = '2017-07-22';
WITH
cte_AddRN AS (
SELECT
o.OrderID, o.ClientName, o.PhoneNumber, o.ServiceDate, o.VehicleID,
RN = ROW_NUMBER() OVER (PARTITION BY o.VehicleID ORDER BY o.ServiceDate)
FROM
#Orders o
WHERE
CAST(o.ServiceDate AS DATE) = #WorkDate
)
SELECT
VehicleName = MAX(v.VehicleName),
Order1 = MAX(CASE WHEN ar.RN = 1 THEN ar.ClientName + ' (' + ar.PhoneNumber + ')' ELSE '' END),
Order2 = MAX(CASE WHEN ar.RN = 2 THEN ar.ClientName + ' (' + ar.PhoneNumber + ')' ELSE '' END),
Order3 = MAX(CASE WHEN ar.RN = 3 THEN ar.ClientName + ' (' + ar.PhoneNumber + ')' ELSE '' END),
Order4 = MAX(CASE WHEN ar.RN = 4 THEN ar.ClientName + ' (' + ar.PhoneNumber + ')' ELSE '' END),
Order5 = MAX(CASE WHEN ar.RN = 5 THEN ar.ClientName + ' (' + ar.PhoneNumber + ')' ELSE '' END)
FROM
#Vehicle v
LEFT JOIN cte_AddRN ar
ON v.VehicleID = ar.VehicleID
GROUP BY
v.VehicleID;
Results...
VehicleName Order1 Order2 Order3 Order4 Order5
----------- --------------- --------------- --------------- --------------- ---------------
Car1
Car2 Jack (11111) Susan (22222)
Car3 Hany (33333) Halaa (55555)

Related

Selecting the n'th range/island of rows where columns have a common value?

I need to select all rows (for a range) which have a common value within a column.
For example (starting from the last row)
I try to select all of the rows where _user_id == 1 until _user_id != 1 ?
In this case resulting in selecting rows [4, 5, 6]
+------------------------+
| _id _user_id amount |
+------------------------+
| 1 1 777 |
| 2 2 1 |
| 3 2 11 |
| 4 1 10 |
| 5 1 100 |
| 6 1 101 |
+------------------------+
/*Create the table*/
CREATE TABLE IF NOT EXISTS t1 (
_id INTEGER PRIMARY KEY AUTOINCREMENT,
_user_id INTEGER,
amount INTEGER);
/*Add the datas*/
INSERT INTO t1 VALUES(1, 1, 777);
INSERT INTO t1 VALUES(2, 2, 1);
INSERT INTO t1 VALUES(3, 2, 11);
INSERT INTO t1 VALUES(4, 1, 10);
INSERT INTO t1 VALUES(5, 1, 100);
INSERT INTO t1 VALUES(6, 1, 101);
/*Check the datas*/
SELECT * FROM t1;
1|1|777
2|2|1
3|2|11
4|1|10
5|1|100
6|1|101
In my attempt I use Common Table Expressions to group the results of _user_id. This gives the index of the last row containing a unique value (eg. SELECT _id FROM t1 GROUP BY _user_id LIMIT 2; will produce: [6, 3])
I then use those two values to select a range where LIMIT 1 OFFSET 1 is the lower end (3) and LIMIT 1 is the upper end (6)
WITH test AS (
SELECT _id FROM t1 GROUP BY _user_id LIMIT 2
) SELECT * FROM t1 WHERE _id BETWEEN 1+ (
SELECT * FROM test LIMIT 1 OFFSET 1
) and (
SELECT * FROM test LIMIT 1
);
Output:
4|1|10
5|1|100
6|1|101
This appears to work ok at selecting the last "island" but what I really need is a way to select the n'th island.
Is there a way to generate a query capable of producing outputs like these when provided a parameter n?:
island (n=1):
4|1|10
5|1|100
6|1|101
island (n=2):
2|2|1
3|2|11
island (n=3):
1|1|777
Thanks!
SQL tables are unordered, so the only way to search for islands is to search for consecutive _id values:
WITH RECURSIVE t1_with_islands(_id, _user_id, amount, island_number) AS (
SELECT _id,
_user_id,
amount,
1
FROM t1
WHERE _id = (SELECT max(_id)
FROM t1)
UNION ALL
SELECT t1._id,
t1._user_id,
t1.amount,
CASE WHEN t1._user_id = t1_with_islands._user_id
THEN island_number
ELSE island_number + 1
END
FROM t1
JOIN t1_with_islands ON t1._id = (SELECT max(_id)
FROM t1
WHERE _id < t1_with_islands._id)
)
SELECT *
FROM t1_with_islands
ORDER BY _id;

changing how oracle output results

please read carefully and if you do not understand what I am saying please let me know.
Below are the tables names and the columns in those tables
table: SYSTEM_USER_SKILL
user_id
skill_id
user_abilities
table: SYSTEM_ADMIN_SKILL
skill_id
skill_name
table: SYSTEM_USER
user_id
user_full_name
I want to write a dynmanic sql or a pl/sql which will display the user_full_name and user_ability.
but I want it to display like this:
p.s. where you see the "Y" and "N" those are results from user_abilities
I dont know how to do this all i know is that it can be done with dynamic sql or pl/sql
Getting the data in tabular form can be done with a pivot, as long as you're on Oracle 11gR2:
select * from (
select su.user_full_name, sas.skill_name, sus.user_abilities
from system_user su
cross join system_admin_skill sas
left join system_user_skill sus on sus.user_id = su.user_id
and sus.skill_id = sas.skill_id
) pivot (max(user_abilities) as able for (skill_name)
in ('php' as php, 'java' as java, 'pl/sql / sql' as plsql_sql,
'Oracle apex' as oracle_apex));
USER_FULL_NAME PHP_ABLE JAVA_ABLE PLSQL_SQL_ABLE ORACLE_APEX_ABLE
-------------------- -------- --------- -------------- ----------------
Sarah woods N N Y Y
John brown N Y Y Y
Johnny paterson Y Y Y Y
Amy brown N N Y N
but you need to list each skill explicitly in the in clause. SQL Fiddle.
In SQL*Plus or SQL Developer you could get the headings you want with something like:
column user_full_name heading "Name"
column php_able format a15 heading "php"
column java_able format a15 heading "java"
column plsql_sql_able format a15 heading "pl/sql / sql"
column oracle_apex_able format a15 heading "Oracle apex"
select ...
Name php java pl/sql / sql Oracle apex
-------------------- --------------- --------------- --------------- ---------------
Sarah woods N N Y Y
John brown N Y Y Y
Johnny paterson Y Y Y Y
Amy brown N N Y N
... but I have no idea if Toad has anything similar.
The non-pivot equivalent of this, which you would have had to use in older versions, would be something like:
select su.user_id, su.user_full_name,
max(case when sas.skill_id = 1 then sus.user_abilities end) as php,
max(case when sas.skill_id = 2 then sus.user_abilities end) as java,
max(case when sas.skill_id = 3 then sus.user_abilities end) as plsql_sql,
max(case when sas.skill_id = 4 then sus.user_abilities end) as oracle_apex
from system_user su
cross join system_admin_skill sas
left join system_user_skill sus on sus.user_id = su.user_id
and sus.skill_id = sas.skill_id
group by su.user_id, su.user_full_name;
This still has all the skills hard-coded in. To allow for additional skills without having to modify the query you'd need to build it dynamically, as shown in earlier answers linked to in comments. In this specific case you could do something like:
create or replace function get_skill_matrix return sys_refcursor as
query varchar2(32767);
rc sys_refcursor;
begin
query := 'select su.user_id, su.user_full_name';
for tmp in (select skill_id, skill_name from system_admin_skill
order by skill_id)
loop
query := query || ', max(case when sas.skill_id = ' || tmp.skill_id
|| ' then sus.user_abilities end) as "'
|| substr(tmp.skill_name, 1, 30) || '"';
end loop;
query := query || ' from system_user su';
query := query || ' cross join system_admin_skill sas';
query := query || ' left join system_user_skill sus on sus.user_id = su.user_id';
query := query || ' and sus.skill_id = sas.skill_id';
query := query || ' group by su.user_id, su.user_full_name';
open rc for query;
return rc;
end;
/
The query string used for the dynamic SQL is just built up to look exactly the same as the static version, but with each skill_id-specific clause generated in a loop from the base system_admin_skill table.
When you call this function you get a cursor back. You haven't really said how or where you're using the results. You can treat it as a result set in a Java program, for example, by executing the function and then calling getCursor() on the statement object. In SQL*Plus or SQL Developer you can use the variable and print commands to display it:
var rc refcursor;
exec :rc := get_skill_matrix;
print rc
In SQL Developer that gives:
anonymous block completed
RC
----------------------------------------------------------------------------------------------
USER_ID USER_FULL_NAME java php pl/sql / sql Oracle apex
--------------------------------------- -------------------- ---- --- ------------ -----------
3 Amy brown N N Y N
4 Sarah woods N N Y Y
2 Johnny paterson Y Y Y Y
1 John brown Y N Y Y
Or in SQL*Plus, where you can do column user_id noprint to hide the ID (which I've included in case two people have the same name!):
Name j p p O
-------------------- - - - -
Amy brown N N Y N
Sarah woods N N Y Y
Johnny paterson Y Y Y Y
John brown Y N Y Y
In Toad I think you can do this, which is all the exec is doing anyway:
begin
:rc := get_skill_matrix;
end;
... and it'll prompt you for the bind type for :rc; if you pick 'ref cursor' it'll show the results in the data grid. Apparently.
OK, same thing but without a function (but still PL/SQL), and including the skill ID in the column alias before truncating to make it unique:
var rc refcursor
declare
query varchar2(32767);
begin
query := 'select su.user_id, su.user_full_name as "Name"';
for tmp in (select skill_id, skill_name from system_admin_skill
order by skill_id) loop
query := query || ', max(case when sas.skill_id = ' || tmp.skill_id
|| ' then sus.user_abilities end) as "'
|| substr(tmp.skill_id || ' ' || tmp.skill_name, 1, 30) || '"';
end loop;
query := query || ' from system_user su';
query := query || ' cross join system_admin_skill sas';
query := query || ' left join system_user_skill sus on sus.user_id = su.user_id';
query := query || ' and sus.skill_id = sas.skill_id';
query := query || ' group by su.user_id, su.user_full_name';
open :rc for query;
end;
/
print rc
Which gives:
RC
-----------------------------------------------------------------------------
USER_ID Name 1 java 2 php 3 pl/sql / sql 4 Oracle apex
-------------- -------------------- ------ ----- -------------- -------------
3 Amy brown N N Y N
4 Sarah woods N N Y Y
2 Johnny paterson Y Y Y Y
1 John brown Y N Y Y

Get the most recent record for each user where value is 'K', action id is null or its state is 1

I have the following tables in SQL Server:
user_id, value, date, action_id
----------------------------------
1 A 1/3/2012 null
1 K 1/4/2012 null
1 B 1/5/2012 null
2 X 1/3/2012 null
2 K 1/4/2012 1
3 K 1/3/2012 null
3 L 1/4/2012 2
3 K 1/5/2012 3
4 K 1/3/2012 null
action_id, state
----------------------------------
1 0
2 1
3 1
4 0
5 1
I need to return the most recent record for each user where the value is 'K', the action id is either null or its state is set to 1. Here's the result set I want:
user_id, value, date, action_id
----------------------------------
3 K 1/5/2012 3
4 K 1/3/2012 null
For user_id 1, the most recent value is B and its action id is null, so I consider this the most recent record, but it's value is not K.
For user_id 2, the most recent value is K, but action id 1 has state 0, so I fallback to X, but X is not K.
user_id 3 and 4 are straightforward.
I'm interested in Linq to SQL query in ASP.NET, but for now T-SQL is fine too.
The SQL query would be :
Select Top 1 T1.* from Table1 T1
LEFT JOIN Table2 T2
ON T1.action_id = T2.action_id
Where T1.Value = 'K' AND (T1.action_id is null or T2.state = 1)
Order by T1.date desc
LINQ Query :
var result = context.Table1.Where(T1=> T1.Value == "K"
&& (T1.action_id == null ||
context.Table2
.Where(T2=>T2.State == 1)
.Select(T2 => T2.action_id).Contains(T1.action_id)))
.OrderByDescending(T => T.date)
.FirstOrDefault();
Good Luck !!
This query will return desired result set:
SELECT
*
FROM
(
SELECT
user_id
,value
,date
,action_id
,ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY date DESC) RowNum
FROM
testtable
WHERE
value = 'K'
) testtable
WHERE
RowNum = 1
You can also try following approach if user_id and date combination is unique
Make sure to get the order of predicates in the join to be able to use indexes:
SELECT
testtable.*
FROM
(
SELECT
user_id
,MAX(date) LastDate
FROM
testtable
WHERE
value = 'K'
GROUP BY
user_id
) tblLastValue
INNER JOIN
testtable
ON
testtable.user_id = tblLastValue.user_id
AND
testtable.date = tblLastValue.LastDate
This would select the top entries for all users as described in your specification, as opposed to TOP 1 which just selects the most recent entry in the database. I'm assuming here that your tables are named users and actions:
WITH usersactions as
(SELECT
u.user_id,
u.value,
u.date,
u.action_id,
ROW NUMBER() OVER (PARTITION BY u.user_id ORDER BY u.date DESC, u.action_id DESC) as row
FROM users u
LEFT OUTER JOIN actions a ON u.action_id = a.action_id
WHERE
u.value = 'K' AND
(u.action_id IS NULL OR a.state = 1)
)
SELECT * FROM usersactions WHERE row = 1
Or if you don't want to use a CTE:
SELECT * FROM
(SELECT
u.user_id,
u.value,
u.date,
u.action_id,
ROW NUMBER() OVER (PARTITION BY u.user_id ORDER BY u.date DESC, u.action_id DESC) as row
FROM users u
LEFT OUTER JOIN actions a ON u.action_id = a.action_id
WHERE
u.value = 'K' AND
(u.action_id IS NULL OR a.state = 1)
) useractions
WHERE row = 1

SQLite Count Summary Query

I'm trying to get a query to summarize each employees work for the week. For example, John Doe did a total of 12 tickets for the week, 4 of which were Break/Fixes, and 4 were Enhancement, and another 4 were uncategorized.
This is what I have so far:
SELECT (users.first_name || ' ' || users.last_name) AS Name,
COUNT(tickets.id) AS 'Number of Tickets Closed',
COUNT(tickets.category = 'Maintenance') AS 'Maintenance Tickets',
COUNT(tickets.category = 'After Hours') AS 'After Hours Tickets',
COUNT(tickets.category = 'Break Fix') AS 'Break Fix Tickets',
COUNT(tickets.category = 'Enhancement') AS 'Enhancement Tickets',
COUNT(tickets.category = '') AS 'Non Categorized Tickets'
FROM tickets, users
ON tickets.assigned_to=users.id
WHERE (tickets.status = 'closed') AND
(tickets.closed_at >= '2011-07-16 00:00:00') AND
(tickets.closed_at <= '2011-07-22 23:59:59')
GROUP BY Name;
Here is a sample result:
John Doe1 10 10 10 10 10 10
John Doe2 2 2 2 2 2 2
John Doe3 25 24 24 24 24 24
John Doe4 2 2 2 2 2 2
John Doe5 12 10 10 10 10 10
John Doe6 7 7 7 7 7 7
This query doesn't quite work as I expected it to as all of the columns have the same total (The total number of tickets closed, the following columns seems to only contain the categorized ones.) Help?
EDIT
Just wanted to post the functional code:
SELECT (users.first_name || ' ' || users.last_name) AS Name,
COUNT(tickets.id) AS 'Number of Tickets Closed',
COUNT(case tickets.category when 'Maintenance' then 1 else null end) AS 'Maintenance Tickets',
COUNT(case tickets.category when 'After Hours' then 1 else null end) AS 'After Hours Tickets',
COUNT(case tickets.category when 'Break Fix' then 1 else null end) AS 'Break Fix Tickets',
COUNT(case tickets.category when 'Enhancement' then 1 else null end) AS 'Enhancement Tickets',
COUNT(case tickets.category when '' then 1 else null end) AS 'Non Categorized Tickets'
FROM tickets, users
ON tickets.assigned_to=users.id
WHERE (tickets.status = 'closed') AND
(tickets.closed_at >= '2011-07-16') AND
(tickets.closed_at <= '2011-07-22')
GROUP BY Name;
you may want to use COUNT like this
...
COUNT(case tickets.category when 'Maintenance' then 1 else null end),
COUNT(case tickets.category when 'After Hours' then 1 else null end),
...
It seems to me you cannot use an alias in the GROUP BY clause. Don't your users have an ID you could use to differenciate them?
And you must use SUM instead of COUNT if you want to count compared with a condition.
SELECT (users.first_name || ' ' || users.last_name) AS Name,
COUNT(tickets.id) AS 'Number of Tickets Closed',
SUM(tickets.category = 'Maintenance') AS 'Maintenance Tickets',
SUM(tickets.category = 'After Hours') AS 'After Hours Tickets',
SUM(tickets.category = 'Break Fix') AS 'Break Fix Tickets',
SUM(tickets.category = 'Enhancement') AS 'Enhancement Tickets',
SUM(tickets.category = '') AS 'Non Categorized Tickets'
FROM tickets, users
ON tickets.assigned_to=users.id
WHERE (tickets.status = 'closed') AND
(tickets.closed_at >= '2011-07-16 00:00:00') AND
(tickets.closed_at <= '2011-07-22 23:59:59')
GROUP BY Name;

T-Sql help needed in Sql Server 2005

I have created one stored procedure which runs on 5000 users in tbluser table with some filter condition in database.There are 4 filtering condition(FC1,FC2,FC3,FC4).Filtering condition has some ListBox and dropdown list of department and countries.I want output as given below:
ID Name StaffNo department Points
1 KK 111 dep1 2
2 NN 222 dep2 1
3 DD 333 dep3 4
I got ID,Name,StaffNo,department in resultset but not points.
points calculation would be based on filtering condition like
if FC1 matched user gained point 1,if both FC1 and FC2 matched user gained 2 point,if both FC1 ,FC2 and FC3 matched user gained 3 point etc.
--in stored procedure i m using dynamic query
DECLARE #SQL VARCHAR(2000)
SET #SQL = 'SELECT U.UserID, U.StaffNo,U.FirstName+'' ''+ U.LastName AS EmployeeName,''?'' AS Points FROM tblUser U '
SET #SQL = #SQL+' WHERE U.Department in (' + #SqlDepartment + ') '
---------------------Update---------------------------------------
IF #SqlLanguage <> ''
SET #SQL = #SQL+' OR U.UserID IN (SELECT UserID FROM Country WHERE LCValues IN ('+ #SqlLanguage +') )'
IF #SqlAreas <> ''
SET #SQL = #SQL+' OR U.UserID IN (SELECT UserID FROM tblAreas WHERE '+#SqlAreas+')'
---------------------Update---------------------------------------
...other filtering condition
EXEC (#SQL)
all filtering condition are implemented with OR logic.
Have you tried implementing a CASE statement to calculate the "Points"?
--in stored procedure i m using dynamic query
DECLARE #SQL VARCHAR(2000)
SET #SQL = '
SELECT
U.[UserID],
U.[StaffNo],
U.[FirstName]+'' ''+ U.[LastName] AS EmployeeName,
(
CASE WHEN EXISTS(SELECT 1 FROM [Country] WHERE /*Your filter comes in here*/) THEN 1 ELSE 0 END +
CASE WHEN EXISTS(SELECT 1 FROM [tblAreas] WHERE /*Your filter comes in here*/) THEN 1 ELSE 0 END +
CASE WHEN EXISTS(SELECT 1 FROM [OtherTable1] WHERE /*Your filter comes in here*/) THEN 1 ELSE 0 END +
CASE WHEN EXISTS(SELECT 1 FROM [OtherTable2] WHERE /*Your filter comes in here*/) THEN 1 ELSE 0 END
) AS Points
FROM [tblUser] U'
SET #SQL = #SQL+' WHERE U.Department in (' + #SqlDepartment + ') OR'...
...other filtering condition
EXEC (#SQL)
I think you might be better off working out the points in your code rather than in the SQL
The only way I can think of doing it is with UNIONS which would be horrible
You can use left outer join to your filter condition, group by UserID to not get duplicates, add a value of 1 for hits and use coalesce to set 0 for no hits.
Some sample code that shows what I mean using Area and Country as filter condition.
declare #U table (UserID int, Name varchar(50), StaffNo char(3), department char(4))
declare #C table (CountryID int, UserID int)
declare #A table (AreaID int, UserID int)
insert into #U values (1, 'KK', '111', 'dep1')
insert into #U values (2, 'NN', '222', 'dep2')
insert into #U values (3, 'DD', '333', 'dep3')
insert into #C values(1, 1)
insert into #C values(2, 1)
insert into #C values(3, 2)
insert into #C values(3, 3)
insert into #A values(1, 1)
insert into #A values(2, 1)
insert into #A values(3, 2)
select
U.UserID,
U.Name,
U.StaffNo,
U.department,
coalesce(C.Point, 0)+coalesce(A.Point,0) as Points
from #U as U
left outer join
(select UserID, 1 as Point
from #C
-- where ...?
group by UserID) as C
on U.UserID = C.UserID
left outer join
(select UserID, 1 as Point
from #A
-- where ...?
group by UserID) as A
on U.UserID = A.UserID

Resources