MS Access 2013 - How do I select unique values from another table? - sql

I have a database with three tables; tbl_Room, tbl_Guest and tbl_RoomGuest (a bit simplified).
`tbl_Room` has information about a certain room
`tbl_Guest` has information about a certain guest
`tbl_RoomGuest` has information about what guest stayed at which room,
and the dates they stayed.
I am making a form where I can enter information about a room, and I want to display a list of the guests that have stayed in that room.
How can I select the names from tbl_Guest, when I want to display unique names of only the guests that stayed in that room?
I want the field to be non-editable.

The query to get the unique names could be written using distinct. Here is an example:
select distinct g.GuestName
from tbl_RoomGuest as rg inner join
tbl_Guest g
on rg.GuestId = rg.GuestId
where rg.RoomId = YOURROOMIDHERE;

Related

Populate SQL query with blank rows

(This is a general SQL question, but I am specifically using MSAccess 2010 so looking for how to do this with Access' flavor of SQL)
I have a table called offices which has id, office_name, num_desks.
Another table called employees which has id, employee_name.
And a final table called employee_offices which has id, office_id, employee_id.
I can assign employees to offices via employee_offices.
I am trying to generate a report which shows all offices and the employees assigned to the, but also includes blank lines for any empty desks in that office.
I realize a "simple" way to do this would be to create a desks table with id, office_id, delete the num_desks column from the offices table and change employee_offices to something like employee_desks. Then my report would be a simple LEFT OUTER JOIN and it would include all the unassigned desks. However for the sake of sanity (in this case, there is no contextual difference between desks), I am not going to do this. Plus if I start deleting desks I have referential constraints to deal with (which obviously exist for a good reason and would catch the fact that I am leaving employees without a desk), but I just want to be able to change the number of desks.
I can calculate the number of empty desks (or lack of desks) through the following command:
SELECT
office_id,
num_desks - num_employees AS desk_diff,
MAX(0, num_desks - num_employees) AS blank_rows_to_add
FROM offices LEFT OUTER JOIN (
SELECT office_id, COUNT(employee_id) AS num_employees
FROM employee_offices
GROUP BY office_Id
) AS num_employees_by_office ON offices.id = num_employees_by_office.office_id
Is there a way to take this number (blank_rows_to_add) and somehow utilze it to add that many blank rows (or at least the row only has the office_id/office_name) to a report showing a list of employees by office? I know this can be done with VBA but I am specifically looking for an SQL method that also doesn't include a temp table if at all possible.
Thank you.

MS Access SQL, sort by age in a specific order

My task: "Compile an SQL query that outputs a specific store (enter parameter window) the age of the youngest buyer"
I´ve tried some things, but because i´m new to SQL and i have no idea what i´m doing non of them seem to work.
I´d really appreciate, if someone would help me.
Thanks!
First you need to know the fields to SELECT (or return) and the table FROM which you are querying (asking) data; let's say you have the following tables: tblStores (containing a list of stores and related info), tblCustomers (containing customers and related info, e.g. ages, names, phone numbers, etc.), and tblPurchases (containing all the purchases at all stores by all customers and related info). You want the minimum age of a customer making a purchase at a specfic store, so you could use a MIN aggregating function. You would want to join (or relate) the tables based on customers and purchases. See my INNER JOINs in the example below. Then you filter the result by the user-inputted store name (inputStoreName) using WHERE; since the inputStoreName is undefined, in Access this would cause the parameter entry popup window to appear.
SELECT list of fields or aggregating functions you want (comma-separated)
FROM list of tables the fields are in (comma-separated) and how to join the tables
WHERE list of conditions to filter the data (separated by AND or OR)
Example:
SELECT tblStores.Name, tblStores.Description, MIN(tblCustomers.age)
FROM tblStores INNER JOIN ( tblPurchases INNER JOIN tblCustomers on tblPurchases.customerID = tblCustomer.customerID) ON tblStores.storeID = tblPurchases.storeID
WHERE (tblStores.Name = inputStoreName);
I recommend checking W3 schools. They are usually helpful for most programming tasks. If you provide more info about your database, we can provide more directed help.

Get all data of users after grouping by

I have two tables "Users" "Bookings" and I merged two tables and groping by the booking and users count and get a new table which has the count of users who made a specific count of bookings ex:
so in the first column (62 users made 3 booking and the second columns 52 users made 4 bookings)
I want to get the data of users when I click on any line on the graph, means when I click on the first line on the graph I want to show the 62 users in a table, can I do this or not?
If you want a SQL solution, it would use group by and having:
select userid
from bookings
group by userid
having count(*) = 3;
This gives the list of user ids. You can use in, exists, or join to get additional information about the users if that is what you really want.

sql: how to query foreign key not based upon ID

My table IncomingLetter has a foreign key to a table Department, which has an ID and a column Short_Name.
I'm using this query to count the incoming letters assigned to a department.
SELECT COUNT(DocumentNumber) AS TotalNumberIncomingLetters
FROM IncomingLetter
WHERE Assigned_To_Department=1;
Whereas this works I want to make a query based upon the short name and not based upon the ID.
SELECT COUNT(DocumentNumber) AS TotalNumberIncomingLetters
FROM IncomingLetter
WHERE Assigned_To_Department.Short_Name="My Department Name";
This does not work, whereas I found examples that are using this syntax. However, it is probably important to notice, that I m using this query in MS access.
You should use
SELECT COUNT(il.DocumentNumber) AS TotalNumberIncomingLetters
FROM IncomingLetter il
INNER JOIN Department d on d.ID = il.Assigned_To_Department
WHERE d.Short_Name="My Department Name";
The "My Department Name" text is actually stored in the Departments table, and only the number (1) is stored in the IncomingLetter table, in the field Assigned_To_Department.
Asking for Assigned_To_Department.Short_Name basically asks the number 1 to get it's Short_Name field, that does not make sense.
You need to tell the database engine two things in these scenarios:
which tables are connected - IncomingLetter and Departments in this case (the inner join part)
how they are connected - by setting their Assigned_To_Department and ID fields respecively (the on ... part

Where are Cartesian Joins used in real life?

Where are Cartesian Joins used in real life?
Can some one please give examples of such a Join in any SQL database.
just random example. you have a table of cities: Id, Lat, Lon, Name. You want to show user table of distances from one city to another. You will write something like
SELECT c1.Name, c2.Name, SQRT( (c1.Lat - c2.Lat) * (c1.Lat - c2.Lat) + (c1.Lon - c2.Lon)*(c1.Lon - c2.Lon))
FROM City c1, c2
Here are two examples:
To create multiple copies of an invoice or other document you can populate a temporary table with names of the copies, then cartesian join that table to the actual invoice records. The result set will contain one record for each copy of the invoice, including the "name" of the copy to print in a bar at the top or bottom of the page or as a watermark. Using this technique the program can provide the user with checkboxes letting them choose what copies to print, or even allow them to print "special copies" in which the user inputs the copy name.
CREATE TEMP TABLE tDocCopies (CopyName TEXT(20))
INSERT INTO tDocCopies (CopyName) VALUES ('Customer Copy')
INSERT INTO tDocCopies (CopyName) VALUES ('Office Copy')
...
INSERT INTO tDocCopies (CopyName) VALUES ('File Copy')
SELECT * FROM InvoiceInfo, tDocCopies WHERE InvoiceDate = TODAY()
To create a calendar matrix, with one record per person per day, cartesian join the people table to another table containing all days in a week, month, or year.
SELECT People.PeopleID, People.Name, CalDates.CalDate
FROM People, CalDates
I've noticed this being done to try to deliberately slow down the system either to perform a stress test or an excuse for missing development deliverables.
Usually, to generate a superset for the reports.
In PosgreSQL:
SELECT COALESCE(SUM(sales), 0)
FROM generate_series(1, 12) month
CROSS JOIN
department d
LEFT JOIN
sales s
ON s.department = d.id
AND s.month = month
GROUP BY
d.id, month
This is the only time in my life that I've found a legitimate use for a Cartesian product.
At the last company I worked at, there was a report that was requested on a quarterly basis to determine what FAQs were used at each geographic region for a national website we worked on.
Our database described geographic regions (markets) by a tuple (4, x), where 4 represented a level number in a hierarchy, and x represented a unique marketId.
Each FAQ is identified by an FaqId, and each association to an FAQ is defined by the composite key marketId tuple and FaqId. The associations are set through an admin application, but given that there are 1000 FAQs in the system and 120 markets, it was a hassle to set initial associations whenever a new FAQ was created. So, we created a default market selection, and overrode a marketId tuple of (-1,-1) to represent this.
Back to the report - the report needed to show every FAQ question/answer and the markets that displayed this FAQ in a 2D matrix (we used an Excel spreadsheet). I found that the easiest way to associate each FAQ to each market in the default market selection case was with this query, unioning the exploded result with all other direct FAQ-market associations.
The Faq2LevelDefault table holds all of the markets that are defined as being in the default selection (I believe it was just a list of marketIds).
SELECT FaqId, fld.LevelId, 1 [Exists]
FROM Faq2Levels fl
CROSS JOIN Faq2LevelDefault fld
WHERE fl.LevelId=-1 and fl.LevelNumber=-1 and fld.LevelNumber=4
UNION
SELECT Faqid, LevelId, 1 [Exists] from Faq2Levels WHERE LevelNumber=4
You might want to create a report using all of the possible combinations from two lookup tables, in order to create a report with a value for every possible result.
Consider bug tracking: you've got one table for severity and another for priority and you want to show the counts for each combination. You might end up with something like this:
select severity_name, priority_name, count(*)
from (select severity_id, severity_name,
priority_id, priority_name
from severity, priority) sp
left outer join
errors e
on e.severity_id = sp.severity_id
and e.priority_id = sp.priority_id
group by severity_name, priority_name
In this case, the cartesian join between severity and priority provides a master list that you can create the later outer join against.
When running a query for each date in a given range. For example, for a website, you might want to know for each day, how many users were active in the last N days. You could run a query for each day in a loop, but it's simplest to keep all the logic in the same query, and in some cases the DB can optimize the Cartesian join away.
To create a list of related words in text mining, using similarity functions, e.g. Edit Distance