MS Access - Run a query displaying one result per user - ms-access-2010

I've got a database that I'm tying into our access control system. I'm trying to create a report showing the user's first entry and last exit from the building. I've put a query together which hows me the right single result for one user, but I want to automate this to run through a list of users.
The query for grabbing the first entry for one user (as it is currently) is as follows:
SELECT TOP 1 AccessLog.ID, AccessLog.Date, First(AccessLog.Time) AS FirstOfTime, AccessLog.User, AccessLog.Details, AccessLog.Event, AccessLog.Department, AccessLog.Where
FROM AccessLog
GROUP BY AccessLog.ID, AccessLog.Date, AccessLog.User, AccessLog.Details, AccessLog.Event, AccessLog.Department, AccessLog.Where
HAVING (((AccessLog.Date)=#DATE#) AND ((AccessLog.User)="USERNAME") AND ((AccessLog.Where)="Front Door (In)"))
ORDER BY First(AccessLog.Time);
I have a separate table of all the usernames, would it be possible to do a run-as for this?
Basically I'm a complete Access n00b, in the past I'd have done this with PHP and a recurring function but this should be fairly easy to achieve within Access, shouldn't it? Any help much appreciated.

You can get a list of the arrival times for all users by date with the following query. Save the query definition under the name "ArriveTimes":
SELECT AccessLog.Date, AccessLog.User, Min(AccessLog.Time) AS ArriveTime
FROM AccessLog
WHERE (((AccessLog.Where)="Front Door (In)"))
GROUP BY AccessLog.Date, AccessLog.User;
Similarly, you can get the departure times with a similar query saved as "DepartTimes":
SELECT AccessLog.Date, AccessLog.User, Max(AccessLog.Time) AS DepartTime
FROM AccessLog
WHERE (((AccessLog.Where)="Front Door (Out)"))
GROUP BY AccessLog.Date, AccessLog.User;
Then you can join the [ArriveTimes] and the [DepartTimes] queries together (JOIN on [Date] and [User]) and pull the other details by joining on two instances of the [AccessLog] table (JOIN on [Date], [User], and [Time]):
SELECT ArriveTimes.Date, ArriveTimes.User,
ArriveTimes.ArriveTime, AccessLog_A.Details AS ArriveDetails,
DepartTimes.DepartTime, AccessLog_D.Details AS DepartDetails
FROM
(AccessLog AS AccessLog_A INNER JOIN
(ArriveTimes INNER JOIN DepartTimes
ON (ArriveTimes.User = DepartTimes.User)
AND (ArriveTimes.Date = DepartTimes.Date)
)
ON (ArriveTimes.ArriveTime = AccessLog_A.Time)
AND (AccessLog_A.User = ArriveTimes.User)
AND (AccessLog_A.Date = ArriveTimes.Date)
)
INNER JOIN AccessLog AS AccessLog_D
ON (DepartTimes.DepartTime = AccessLog_D.Time)
AND (DepartTimes.User = AccessLog_D.User)
AND (DepartTimes.Date = AccessLog_D.Date);

Related

How to get all the elements of an association?

I have created a CDS views as follows:
define view YGAC_I_REQUEST_ROLE
with parameters
pm_req_id : grfn_guid,
#Consumption.defaultValue: 'ROL'
pm_item_type : grac_prov_item_type,
#Consumption.defaultValue: 'AP'
pm_approval : grac_approval_status
as select from YGAC_I_REQ_PROVISION_ITEM as provitem
association [1..1] to YGAC_I_ROLE as _Role on _Role.RoleId = provitem.ProvisionItemId
association [1..*] to YGAC_I_ROLE_RS as _Relation on _Relation.RoleId1 = provitem.ProvisionItemId
{
key ReqId,
key ReqIdItem,
Connector,
ProvisionItemId,
ActionType,
ValidFrom,
ValidTo,
_Role.RoleId,
_Role.RoleName,
_Role.RoleType,
_Role,
_Relation
}
where
ReqId = $parameters.pm_req_id
and ProvisionItemType = $parameters.pm_item_type
and ApprovalStatus = $parameters.pm_approval
Then I have consumed in ABAP:
SELECT
FROM ygac_i_request_role( pm_req_id = #lv_test,
pm_item_type = #lv_item_type,
pm_approval = #lv_approval
)
FIELDS reqid,
connector,
provisionitemid
INTO TABLE #DATA(lt_result).
How to get the list of _Relation according to selection above.
This is generally not possible like in ABAP SQL queries:
SELECT m~*, kt~*
FROM mara AS m
JOIN makt AS kt
...
This contradicts the whole idea of CDS associations, because they were created to join on-demand and to reduce redundant calls to database. Fetching all fields negates the whole idea of "lazy join".
However, there is another syntax in FROM clause which is enabled by path expressions that allows querying underlining associations both fully and by separate elements. Here is how
SELECT *
FROM ygac_i_request_role( pm_req_id = #lv_test )
\_Role AS role
INTO TABLE #DATA(lt_result).
This fetches all the fields of _Role association into internal table.
Note: remember, it is not possible to fetch all the published associations of current view simultaneously, only one path per query.
Possible workaround is to use JOIN
SELECT *
FROM ygac_i_request_role AS main
JOIN ygac_i_request_role
\_Role AS role
ON main~ProvisionItemId = role~RoleId
JOIN ygac_i_request_role
\_Relation AS relation
ON main~ProvisionItemId = relation~RoleId1
INTO TABLE #DATA(lt_table).
This creates deep-structured type with dedicated structure for every join association like this:
If you are not comfortable with such structure for you task, lt_table should be declared statically to put up all the fields in a flat way
TYPES BEGIN OF ty_table.
INCLUDE TYPE ygac_i_request_role.
INCLUDE TYPE ygac_i_role.
INCLUDE TYPE ygac_i_role_rs.
TYPES END OF ty_table.

how to use join with Sqlite Index

I am creating a app with ionic 3. In the app I added a search filter which filter users according to their role. I have 5 tables from which I have to pull the data.In term to do so, I did these steps..
created each table index with the required data.
CREATE INDEX IF NOT EXISTS AccountIndexTable ON Accounts(id,roleId,firstName,lastName,email,accountId);
CREATE INDEX IF NOT EXISTS AddressIndexTable ON Addresses(id,addressTypeId,street,city,state,country,pincode,accountId)
CREATE INDEX IF NOT EXISTS CompanyIndexTable ON Companies(id,name,accountId)
CREATE INDEX IF NOT EXISTS CommunicationIndexTable ON Communications(id,phone,accountId)
CREATE INDEX IF NOT EXISTS OptionalInfoIndexTable ON CustomerOptionalInfos(id,customerType,accountId)
and then i used join to get data. Before that I have questions
1: Do I need to use the indexed table in my join?
the Join query:
SELECT Accounts.accountId AS accountID,
Accounts.roleId AS roleID,
Accounts.email AS email,
Accounts.firstName || " " || Accounts.lastName AS name,
Addresses.street AS street,
Addresses.city AS city,
Addresses.state AS state,
Addresses.country AS country,
Addresses.pincode AS pincode,
Communications.phone AS phone,
Companies.name AS compName,
CustomerOptionalInfos.customerType AS cType
FROM Accounts
LEFT JOIN Addresses ON Addresses.accountId=Accounts.accountId
AND Addresses.addressTypeId=1
LEFT JOIN Communications ON Communications.accountId=Accounts.accountId
LEFT JOIN Companies ON Companies.accountId=Accounts.accountId
LEFT JOIN CustomerOptionalInfos ON CustomerOptionalInfos.accountId=Accounts.accountId
WHERE 1=1
AND Accounts.isDelete!='true'
AND Accounts.firstName!= ''
AND Accounts.roleId = 5
ORDER BY Accounts.firstName ASC
LIMIT ?,?
It still takes +2 seconds to execute. Please suggest me the better way of doing this. I have a large number of data.

SQLITE : inline views or nested subqueries?

I'm trying to write a query on two simple tables. Tables are simple, the query is not :)
Anyway...
Here is the database scheme :
and here is an overview of table content :
I'm trying to write a query that would list all assets in corresponding table, only if the are marked as "wanted" (meaning the boolean field asset_owned =0) and that are referenced for another owner as "owned".
This is what I have so far and it works :
SELECT
user.user_pseudo AS REQUESTER,
asset.asset_sku AS SKU,
asset.asset_name AS ASSET_NAME
FROM
asset
INNER JOIN user ON asset.id_user = user.id
WHERE
asset.asset_owned = 0
AND
asset.asset_sku IN (SELECT asset.asset_sku FROM asset WHERE asset.asset_owned = 1)
But, in the same query (if possible) I would like to get the owner name as well.
The first result of such a query on those table would be :
me,003,Test003,you.
I've tried inline SELECT and nested subqueries like :
SELECT
user.user_pseudo as ASKER,
asset.asset_sku as SKU,
asset.asset_name as NAME,
subquery1.user.user_pseudo as OWNER
FROM
asset
INNER JOIN user ON asset.id_user = user.id,
(SELECT user.user_pseudo.asset_asset_sku FROM asset INNER JOIN user ON asset.id_user = user.id WHERE asset.asset_owned = 1) subquery1
WHERE
asset.asset_owned = 0 AND
subquery1.asset.asset_sku IN (SELECT asset.asset_sku FROM asset INNER JOIN user ON asset.id_user = user.id WHERE asset.asset_owned=1)
but of course that does not work.
Thanks for any direction you could point me to.
happy new year
Mathias
So this was fun for me (I'm learning SQL, so this is good practice!) - I appreciate the very clear question.
Hopefully this works for you - I used two sub-queries (one each for 'owner' and 'requester') and then joined those on SKU and name. It works in SQLite with the small sample data shown above.
SELECT requester, subq1.SKU, subq1.name, owner
FROM
(SELECT pseudo AS requester, SKU, name
FROM asset, user
WHERE owned = 0
AND user.id = id_user) subq1,
(SELECT pseudo AS owner, SKU, name
FROM asset, user
WHERE owned = 1
AND asset.id_user = user.id) subq2
WHERE subq1.SKU = subq2.SKU
AND subq1.name = subq2.name;

Multiple column SQL joins in a table

Background:
Hi there, first time posting a question so please excuse any wrongdoings...
I have been given an assignment at university using ASP.NET and SQL Server, what we basically have to do is create a webform where we can select a political party via a radio button list bound to a SQL data source. Based on this selection, a drop-down list is then populated with a list of MPs who are a part of the party selected the radio button list. You can then select an MP and view his or her personal details, their roles in parliament and ask/view questions via a number of data controls linked to various SQL data sources.
I'm making good progress and trying to use whatever resources I can find to get solutions but alas I've hit a wall with viewing the parliamentary roles after selecting the MP.
I have 3 tables which are involved here:
MP MP_ROLES ROLE
------------- --------------- ----------------
MP_NUM (PK) MP_NUM (PK, FK) ROLE_NUM (PK)
MP_FIRST ROLE_1 (FK) ROLE_DESCRIPTION
MP_LAST ROLE_2 (FK)
MP_EMAIL ROLE_3 (FK)
MP_CONTACTADD ROLE_4 (FK)
MP_PHOTO
PARTY_NUM(FK)
(where ROLE_1 through ROLE_4 reference ROLE.ROLE_NUM.)
Problem:
I have a DetailsView control which is bound to an SQL data source which queries MP_ROLES. What I'm basically trying to do is replace each value in ROLE_1, ROLE_2, etc. with the corresponding ROLE_DESCRIPTION value referenced by ROLE_NUM in the ROLE table (as MP_ROLE.ROLE_1 = ROLE.ROLE_NUM AND MP_ROLE.ROLE_2 = ROLE.ROLE_NUM AND MP_ROLE.ROLE_3 = ROLE.ROLE_NUM AND MP_ROLE.ROLE_4 = ROLE.ROLE_NUM). Now through my digging through textboxes I know in more simple applications you can do what I'm trying to do with the INNER JOIN function, however as I'm still learning I haven't quite got the syntax sorted to do what I want to do.
What I have so far:
SELECT MP_ROLES.MP_NUM, MP_ROLES.ROLE_1, MP_ROLES.ROLE_2, MP_ROLES.ROLE_3, MP_ROLES.ROLE_4
FROM MP_ROLES
INNER JOIN ROLE ON MP_ROLES.ROLE_1 = ROLE.ROLE_NUM
INNER JOIN ROLE AS ROLE_3 ON MP_ROLES.ROLE_2 = ROLE.ROLE_NUM
INNER JOIN ROLE AS ROLE_2 ON MP_ROLES.ROLE_3 = ROLE.ROLE_NUM
INNER JOIN ROLE AS ROLE_1 ON MP_ROLES.ROLE_4 = ROLE.ROLE_NUM
WHERE (MP_ROLES.MP_NUM = #MP_NUM)
I've been hung up on this for the last 8 trying to find a solution so if there is anyone who is able show me where I'm going wrong or perhaps kind enough to provide a solution it would be very much appreciated :)
Your problem lies in the = ROLE.ROLE_NUM. You have to specify the alias here too. Also I rearranged some numbers since your numbers were all mixed up.
SELECT MP_ROLES.MP_NUM
, MP_ROLES.ROLE_1
, MP_ROLES.ROLE_2
, MP_ROLES.ROLE_3
, MP_ROLES.ROLE_4
FROM MP_ROLES
INNER JOIN ROLE AS ROLE_1 ON MP_ROLES.ROLE_1 = ROLE_1.ROLE_NUM
INNER JOIN ROLE AS ROLE_2 ON MP_ROLES.ROLE_2 = ROLE_2.ROLE_NUM
INNER JOIN ROLE AS ROLE_3 ON MP_ROLES.ROLE_3 = ROLE_3.ROLE_NUM
INNER JOIN ROLE AS ROLE_4 ON MP_ROLES.ROLE_4 = ROLE_4.ROLE_NUM
WHERE (MP_ROLES.MP_NUM = #MP_NUM)
It looks as though what I was actually aiming for can be done using the LEFT OUTER JOIN function:
SELECT
MP_ROLES.MP_NUM,
MP_ROLES.ROLE_1,
MP_ROLES.ROLE_2,
MP_ROLES.ROLE_3,
MP_ROLES.ROLE_4,
ROLE1.ROLE_NUM, ROLE1.ROLE_DESCRIPTION AS POSITION1,
ROLE2.ROLE_NUM, ROLE2.ROLE_DESCRIPTION AS POSITION2,
ROLE3.ROLE_NUM, ROLE3.ROLE_DESCRIPTION AS POSITION3,
ROLE4.ROLE_NUM, ROLE4.ROLE_DESCRIPTION AS POSITION4
FROM MP_ROLES
LEFT OUTER JOIN ROLE AS ROLE1 ON MP_ROLES.ROLE_1 = ROLE1.ROLE_NUM
LEFT OUTER JOIN ROLE AS ROLE2 ON MP_ROLES.ROLE_2 = ROLE1.ROLE_NUM
LEFT OUTER JOIN ROLE AS ROLE3 ON MP_ROLES.ROLE_3 = ROLE1.ROLE_NUM
LEFT OUTER JOIN ROLE AS ROLE4 ON MP_ROLES.ROLE_4 = ROLE1.ROLE_NUM
WHERE (MP_ROLES.MP_NUM = #MP_NUM)

Linq to Entities: Left join to get items NOT found in the join

I've got two un-related (no FK's defined) tables. The first table contains some tasks for which a user may not have access. I need to find all those tasks - in this case, the joined table would contain nulls. How do I get them?
Here's the setup:
TimeData table
- userID
- taskID
- hours
ApprovedTasks table (the one that should contain nulls)
- taskID
- userID
The SQL query would look like this:
select * from TimeData td
left join ApprovedTasks at
on at.taskID = td.taskID and at.userID = td.userID
where at.taskID is null
Any way to pull that off using a LINQ to Entity query?
TIA
Check out... Disjoint Union in LINQ
This should work...
var approvedTaks = from at in ApprovedTasks.Except(
from at2 in ApprovedTasks
where at2.userID == userId and at2.taskID==taskId
select at2)
where at.userID == userId and at.taskID==taskId
select at;
but sorry don't have the database handy to test it.

Resources