how to use distinct in ms access - sql

I have two tables. Task and Categories.
TaskID is not a primary key as there are duplicate values.When there are multiple contacts are selected for a specific task,taskid and other details will be duplicated.I wrote the query:
SELECT Priority, Subject, Status, DueDate, Completed, Category
FROM Task, Categories
WHERE Categories.CategoryID=Task.CategoryID;
Now as multiple contacts are selected for that task,for the taskid=T4, there are two records(highlighted with gray). I have tried using distinct in ms access 2003 but its not working. I want to display distinct records. (Here there's no requirement to show taskid) If I write :
select priority, distinct(subject), .......
and remaining same as mentioned in above query then its giving me an error. I have tried distinctrow also.But didnt get success. How to get distinct values in ms access?

Okay.Its working this way.
SELECT DISTINCT Task.Priority, Task.Subject, Task.Status, Task.DueDate,
Task.Completed, Categories.Category
FROM Task, Categories
WHERE (((Categories.CategoryID)=[Task].[CategoryID]));

I don't like using SELECT DISTINCT, I have found that it makes my code take longer to compile. The other way I do it is by using GROUP BY.
SELECT Priority, Subject, Status, DueDate, Completed, Category
FROM Task, Categories
WHERE Categories.CategoryID=Task.CategoryID
GROUP BY Subject;
I do not have VBA up at the moment but this should work as well.

Using SELECT DISTINCT will work for you, but a better solution here would be to change your database design.
Duplicate records may lead to inconsistent data. For example, imagine having two different status in different records with the same TaskID. Which one would be right?
A better design would include something like a Task table, a Contact table and an Assignment table, as follows (the fields in brackets are the PK):
Tasks: [TaskID], TaskPriority, Subject, Status, DueDate, Completed, StartDate, Owner, CategoryID, ContactID, ...
Contact: [ID], Name, Surname, Address, PhoneNumber, ...
Assignment: [TaskID, ContactID]
Then, you can retrieve the Tasks with a simple SELECT from the Tasks tables.
And whenever you need to know the contacts assigned to a Tasks, you would do so using the JOIN clause, like this
SELECT T.*, C.*
FROM TaskID as T
INNER JOIN Assignment as A
ON T.TaskID = A.TaskID
INNER JOIN Contac as C
ON A.ContactID = C.ID
Or similar. You can filter, sort or group the results using all of SQL's query power.

Related

Grouping other fields by common email

I'd appreciate any assistance people could provide with this one. I've tried to follow a couple of other posts (GROUP BY to combine/concat a column), but when I do this, it combines everything.
I have a table in SQL that holds contact data. Some contacts in the database have the same email address, particularly admin#, accounts#, etc. We also have a list of contact preferences for each contact: Emergency Contact, Accounts, WHS, etc. I'm trying to select the results of the table, but only one row per email address.
My data looks like this:
However, I'd like it to group the rows together that have the same email address (I don't care about the names). I'd also like it to look at the contact preference fields and if even one of the joined fields had a yes, show a Y, otherwise show a N - see below example
As I mentioned, all my tests have been unsuccessful I'm afraid, so I would appreciate any assistance that you can provide.
You can use the following:
;WITH selected as (
select min(ContactID) as ContactID, Mail, max(EmergencyContact) as EmergencyContact,
max(AccountsCon) as AccountsCon, max(WHSContact) as WHSContact
from t
GROUP BY Mail
)
select t.ContactID, t.BusinessID, t.BusinessName, t. FirstName, t.LastName, t.Position, t.Mail, s.EmergencyContact, s.AccountsCon, s.WHSContact
from selected as s
inner join t as t ON t.ContactID = s.ContactID
This way you get the contactid, businessid, businessname, firstname, lastname and position from the first record found with each email and the last 3 columns you get using max (taking advantage that Y is greater than N, so if there is at least one Y it will get Y).
I think you can just use aggregation:
select businessid, businessname, max(firstname),
max(lastname), max(position),
email,
max(emergencycontact),
max(accountscor),
max(whcontact)
from t
group by businessid, businessname, email;

How to make all rows in a table identical which the exception of 1 field?

I am trying to make it so all the users have the same items because I am doing an experiment with my app and need the experimental control of flattened data.
I used the following SQL statement in my last attempt:
insert into has (email,id,qty,price,item_info,image)
select 'b#localhost.com',id,qty,price,item_info,image
from
(
select * from has
where email != 'b#localhost.com'
) as o
where o.id not in
(
select id from has
where email = 'b#localhost.com'
);
This should add all items which 'b#localhost.com' does not already have but other users do have, to 'b#localhost.com's inventory. (the 'has' table)
However, I get the following error:
The statement was aborted because it would have caused a duplicate key value in a unique or primary key constraint or unique index
I understand what this error means, but I do not understand why it is occurring. My statement inserts all records which that email doesn't already have, so there should not be any duplicate id/email pairs.
The database structure is shown below, circles are attributes, squares are tables, and diamonds are relationship sets. The HAS table is a relationship set on USER_ACCOUNT and ITEM, where the primary keys are email and id respectively.
Please try the following...
INSERT INTO has ( email,
id,
qty,
price,
item_info,
image )
SELECT a.email,
b.id,
a.qty,
a.price,
a.item_info,
a.image
FROM has a
CROSS JOIN has b
JOIN
(
SELECT email,
id
FROM has
) c ON a.email = c.email AND
b.id <> c.id;
The CROSS JOIN appends a copy of each row of has to each row of has. Please see http://www.w3resource.com/sql/joins/cross-join.php for more information on CROSS JOIN's.
Each row of the resulting dataset will have two id fields, two email fields, two qty fields, etc. By giving each instance of has an alias we create the fields a.id, b.id, a.email, etc.
We then compare each combination of "old" email address and "new" id to a list of existing email / id combinations and insert the old values with the new id replacing the old one into has
If you have any questions or comments, then please feel free to post a Comment accordingly.
Further Reading
http://www.w3resource.com/sql/joins/cross-join.php for more information on CROSS JOIN's
https://www.w3schools.com/sql/sql_in.asp for more information on WHERE's IN operator
https://www.w3schools.com/sql/sql_groupby.asp for more information on GROUP BY
I think the issue here is not that the code is trying to insert something which already exists, but that it's trying to insert more than one thing with the same PK. In lieu of an response to my comment, here is one way to get around the issue:
INSERT INTO has (email,id,qty,price,item_info,image)
SELECT
'b#localhost.com',
source.id,
source.qty,
source.price,
source.item_info,
source.image
FROM
(
SELECT email, id, qyt, price, item_info, image FROM has
) as source
JOIN
(
SELECT min(email) as min_email, id FROM has GROUP BY by id)
) as filter ON
filter.min_email = source.email
WHERE
source.id not in
(
SELECT id from has WHERE email = 'b#localhost.com'
);
The key difference from your original code is my extra join to the subquery I've aliased as filter. This limits you to inserting the has details from a single email per id. There are other ways to do the same, but I figured that this would be a safe bet for being supported by Derby.
I removed the WHERE clause from the source sub-query as that is handled by the final WHERE.

Using multiple columns with counts in access database designer

I am trying to display several columns with different counts in a microsoft access query. It doesn't let me do certain things a normal query can b/c it has the sql design view.
I'd like to display
multiple single etc columns with their counts.
Note: the table names and attributes have been changed.
select (select count(*)as multiple from (select userId from dbo.Purchases
where userId is not null GRoup by userId having count(*)>1) x), (
select count(*)as single from (select userId from dbo.Purchases where
userId is not null GRoup by userId having count(*)=1) x );
if I do these separately I can display it, but I'd like to combine them into one query and one row. Is this possible?
select count(*)as multiple from (select userId from dbo.Purchases
where userId is not null GRoup by userId having count(*)>1) x)
It's very easy with 2 queries:
First one, saved as "Purchases Summary"
Select UserID, count(UserID) as Count from Purchases Group By UserID
With a 2nd built on it:
SELECT Sum(IIf([count]=1,1)) AS [Single], Sum(IIf([count]>1,1)) AS Multiple FROM [Purchases Summary]
I cannot find a clever way to combine this into a single query.
I don't know what my problem last night was, but the single query is
SELECT Sum(IIf([count]=1,1)) AS [Single], Sum(IIf([count]>1,1)) AS Multiple
FROM (Select UserID, count(UserID) as Count from Purchases Group By UserID)
Don George solution also would work.
I ended up using a form and VBA for each column. An issue I had was that I needed to use a distinct call for unique IDs and when there is a sql design view that's not really supported. distinctrow is supported, but it would not work for my query. I ended up writing it as before so that it did not need distinct.
This is the VBA I used to override each input inside of an access form. The currentDb needs to be connected to the database properly before it will also work.
selectStatement = "SELECT Count(* ) FROM (SELECT userID FROM dbo_Purchases WHERE userID is not null GROUP BY userID HAVING count(*)>1) AS x;"
rs = CurrentDb.OpenRecordset(selectStatement).Fields(0).Value
[Text30].Value = rs

SOQL, Salesforce - Join Two objects with two where clauses

I have two objects named as 'Opportunity' and 'Account.
I need to select ID, OpportunityName,CreatedDate from Opportunity table and AccountName, AccountCat from Account table where Account.OpportunityID = Opportunity.ID and AccountCat = 'DC'.
I refer this tutorial and executed in workbench, but didn't work.
Following is the query I used.
SELECT AccountName, AccountCat (SELECT Id, OpportunityName,CreatedDate FROM Opportunity) FROM Account WHERE OpportunityID
IN (SELECT Id FROM Opportunity) AND AccountCat = 'DC'
Run your query on the Opportunity object and then use reference fields to select fields from the parent object.
SELECT Id
, Name
, CreatedDate
, Account.Name
FROM Opportunity
WHERE Account.Name = 'GenePoint'
AccountCat is not a standard field, so I assume it's a custom field, in which case you need to use the developer name, probably something like Account.Cat__c or Account.Category__c or something like that.
SOQL is superficially similar to SQL, but there are significant differences, one of them being how records are joined.

Can peewee nest SELECT queries such that the outer query selects on an aggregate of the inner query?

I'm using peewee2.1 with python3.3 and an sqlite3.7 database.
I want to perform certain SELECT queries in which:
I first select some aggregate (count, sum), grouping by some id column; then
I then select from the results of (1), aggregating over its aggregate. Specifically, I want to count the number of rows in (1) that have each aggregated value.
My database has an 'Event' table with 1 record per event, and a 'Ticket' table with 1..N tickets per event. Each ticket record contains the event's id as a foreign key. Each ticket also contains a 'seats' column that specifies the number of seats purchased. (A "ticket" is really best thought of as a purchase transaction for 1 or more seats at the event.)
Below are two examples of working SQLite queries of this sort that give me the desired results:
SELECT ev_tix, count(1) AS ev_tix_n FROM
(SELECT count(1) AS ev_tix FROM ticket GROUP BY event_id)
GROUP BY ev_tix
SELECT seat_tot, count(1) AS seat_tot_n FROM
(SELECT sum(seats) AS seat_tot FROM ticket GROUP BY event_id)
GROUP BY seat_tot
But using Peewee, I don't know how to select on the inner query's aggregate (count or sum) when specifying the outer query. I can of course specify an alias for that aggregate, but it seems I can't use that alias in the outer query.
I know that Peewee has a mechanism for executing "raw" SQL queries, and I've used that workaround successfully. But I'd like to understand if / how these queries can be done using Peewee directly.
I posted the same question on the peewee-orm Google group. Charles Leifer responded promptly with both an answer and new commits to the peewee master. So although I'm answering my own question, obviously all credit goes to him.
You can see that thread here: https://groups.google.com/forum/#!topic/peewee-orm/FSHhd9lZvUE
But here's the essential part, which I've copied from Charles' response to my post:
I've added a couple commits to master which should make your queries
possible
(https://github.com/coleifer/peewee/commit/22ce07c43cbf3c7cf871326fc22177cc1e5f8345).
Here is the syntax,roughly, for your first example:
SELECT ev_tix, count(1) AS ev_tix_n FROM
(SELECT count(1) AS ev_tix FROM ticket GROUP BY event_id)
GROUP BY ev_tix
ev_tix = SQL('ev_tix') # the name of the alias.
(Ticket
.select(ev_tix, fn.count(ev_tix).alias('ev_tix_n'))
.from_(
Ticket.select(fn.count(Ticket.id).alias('ev_tix')).group_by(Ticket.event))
.group_by(ev_tix))
This yields the following SQL:
SELECT ev_tix, count(ev_tix) AS ev_tix_n FROM (SELECT Count(t2."id")
AS ev_tix FROM "ticket" AS t2 GROUP BY t2."event_id")
GROUP BY ev_tix