I am using this sql statement to join two tables together where the return_date in one table is null.
SELECT
Customers.CustomerID, Customers.First_Name,
Customers.Surname, Customers.House_No,
Customers.Street, Customers.County, Customers.Postcode,
IssueBook.Return_Date
FROM
Customers
INNER JOIN
IssueBook ON Customers.CustomerID = IssueBook.CustomerID
WHERE
((IssueBook.Return_Date IS NOT Null));
This statement is then used to fill a datagrid on a form. However when I view the datagrid they're could be duplicated rows as the customer may have taken more than one book out( just so you know I'm creating a library system). This means there is duplicated data. I know I can do a SELECT DISTINCT statement and delete the other rows and put the DISTINCT rows back in but I'm not sure how to do this as can I use a DISTINCT statement on the datagrid or will it have to be on the INNER JOIN sql statement? Please help?
Just put DISTINCT in the SQL query right next to the SELECT. You should have no problems as the DataGridView is GUI object from .NET and is completely independent from the database. It can show any tabular data you provide to it, whether it contains duplicates or not.
SELECT DISTINCT
Customers.CustomerID, Customers.First_Name,
...
Related
I'm currently in the process of converting an access database to SQL. While going through it, I found this.
Update EmployeeCustomerOrderDetail set Valid = -1;
This is strange because EmployeeCustomerOrderDetail is a query, defined below.
Select *
From Employee
inner join Order on Employee.EmployeeID = Order.EmployeeID
inner join Customer on Order.CustomerID = Customer.CustomerID
inner join OrderDetail on Order.OrderID = OrderDetail.OrderID
I thought that this achieved nothing since an Update on a Select wouldn't work, but I tested it with
Update (Select * From Employees) as Emp set Emp.WorkPhone as 'Random Value'
And it worked.
My question then, is how is this processed. Does the update traverse backwards through all query tables until it finds a dataTable? Will it change the value of a reference column, or the actual data in the associated table?
This only works with updateable recordsets. It's the same as just changing a value directly in the Access query.
In an updateable recordsets, each field in the dataset (query) is directly bound to a field in a table. This means updates directly affect the underlying tables of a query. You can review this answer for rules about which recordsets are and aren't updateable.
Another really contra-intuitive thing about this is that recordsets with outer joins can be contain updateable unmatched records. In this case, a record is created in the table that doesn't contain a matched record, then a new one gets created.
I have a table that contains several repair categories, and items that are associated with each repair category. I am trying to insert all the standard items from a specific repair category that don't already exist into a Details table.
TblEstimateDetails is a join table for an Estimate Table and StandardItem Table. And TblCategoryItems is a join table for the Repair Categories and their respective Standard Items.
For example in the attached image, Left side are all the Standard Items in a Repair Category, and Right side are all the Standard Items that are already in the EstimateDetails table.
Standard Items All vs Already Included
I need to be able to insert the 6 missing GUIDS from the left, and into the table on the right, and only for a specific estimate GID.
This is being used in an Access VBA script, which I will translate into the appropriate code once I get the sql syntax correct.
Thank you!
INSERT INTO TblEstimateDetails(estimate_GID, standard_item_GID)
SELECT
'55DEEE29-7B79-4830-909C-E59E831F4297' AS estimate_GID
, standard_item_GID
FROM TblCategoryItems
WHERE repair_category_GID = '32A8AE6D-A512-4868-8E1A-EF0357AB100E'
AND NOT EXISTS
(SELECT standard_item_GID
FROM TblEstimateDetails
WHERE estimate_GID = '55DEEE29-7B79-4830-909C-E59E831F4297');
Some things to try: 1) simplify to a select query to see if it selects the right records, 2) use a NOT IN statement instead of NOT EXISTS. There's no reason NOT EXISTS shouldn't work, I'd just try a different way if it isn't working.
SELECT '55DEEE29-7B79-4830-909C-E59E831F4297' AS estimate_GID,
standard_item_GID
FROM TblCategoryItems
WHERE repair_category_GID = '32A8AE6D-A512-4868-8E1A-EF0357AB100E'
AND standard_item_GID NOT IN
(SELECT standard_item_GID FROM TblEstimateDetails
WHERE estimate_GID = '55DEEE29-7B79-4830-909C-E59E831F4297');
Got it figured out. Access needs the subquery to be correlated to main query to work. So I set the WHERE clause in the subquery to equal the matching column in the main query. And I had to join the Estimates table so that it picked only the items in a specific estimate.
SELECT
'06A2E0A9-9AE5-4073-A856-1CCE6D9C48BB' AS estimate_GID
, CI.standard_item_GID
FROM TblCategoryItems CI
INNER JOIN TblEstimates E ON CI.repair_category_GID=E.repair_category_GID
WHERE E.repair_category_GID = '15238097-305E-4456-B86F-3787C9B8219B'
AND NOT EXISTS
(SELECT ED.standard_item_GID
FROM TblEstimateDetails ED
WHERE E.estimate_GID=ED.estimate_GID
);
I have an ACCESS BD with a main table ('Principale') having a many-to-many connection with another ('TabRegisti'), with a join table between them ('TabRegisti_Unione').
I've a form for 'Principale' where there's a Search Button that, after the user click, creates a query for a listbox in another form.
The query that I'm using is the following:
SELECT Principale.ID, Principale.CodiceDVD, Principale.Cofanetto,
Principale.TitoloDVD, TabRegisti.NomeRegista, TabRegisti.CognomeRegista,
TabCategoria.Categoria, Principale.Durata, Principale.AttoriPrincipali,
Principale.Produzione, Principale.AnnoDVD, Principale.AnnoFilm,
Principale.DataACQ, Principale.Ubicazione
FROM TabRegisti
INNER JOIN (TabCategoria
INNER JOIN ((Principale INNER JOIN TabUbicazione
ON Principale.Ubicazione = TabUbicazione.Ubicazione)
INNER JOIN TabRegisti_unione
ON Principale.ID = TabRegisti_unione.IDrifPrincipale)
ON TabCategoria.CategorieID = Principale.CategorieID)
ON TabRegisti.IDRegista = TabRegisti_unione.IDregistaUnione
WHERE (((TabRegisti.NomeRegista) Like "*anc*")
AND ((TabRegisti.CognomeRegista) Like "*"))
ORDER BY Principale.CodiceDVD;
I'm using the query, with the correct syntax, in VBA (the Where clause showed is just an example, of course).
It works fine but leaves duplicates of the main table's records.
I've tried to insert the clause DISTINCT and, after, the clause DISTINCTROW, but nothing chanced (duplicates are still there).
Otherwise, the use of the clause GROUP BY (i.e. 'GROUP BY Principale.CodiceDVD' before the clause ORDER BY) gives an error. Suggstions?
Hope the explanation of the problem is clear enough (I'm not english motherlanguage, so be indulgents).
DISTINCT will show only rows with distinct values in your selection fields. Your selected fields row must not be actually identical. You need to remove from the SELECT fields the once that you probably don't need and that generate a row that you don't want to see.
This is an MS Access (2010) script.
I am trying to concatenate 2 fields of a single table for 2 tables. Then I want to delete the associated record in one of the table if the concatenated field is equal in both tables (means this is a duplicate).
I know how to do that in VBA by looping through the records but I want to do that in SQL since the tables may quickly hold more than 50000 records which means the loop would go 2,500,000,000 times.
I though I could create a 2 SELECT statement in order to create the concatenated fields for both tables. The SELECT Statements will also display the ID of the underlying tables. Then I would delete the record in the appropriate table using the ID.
These are my Select statements:
SELECT [Tick] & [Div_ex_date] AS Expr2, tblBbgDivData.ID
FROM tblBbgDivData
GROUP BY [Tick] & [Div_ex_date], tblBbgDivData.ID;
And
SELECT [Security_Name] & [Div_ex_date] AS Expr1, tblArchiveBbgDivData.ID
FROM tblArchiveBbgDivData
GROUP BY [Security_Name] & [Div_ex_date], tblArchiveBbgDivData.ID;
This is my DELETE Statement:
DELETE tblArchiveBbgDivData.*
FROM (tblArchiveBbgDivData
INNER JOIN qselUniqueID_Archive ON tblArchiveBbgDivData.ID = qselUniqueID_Archive.ID)
INNER JOIN qselUniqueID_BbgDiv ON qselUniqueID_Archive.Expr1 = qselUniqueID_BbgDiv.Expr2
WHERE (((tblArchiveBbgDivData.ID)=[qselUniqueID_Archive].[ID])
AND ((qselUniqueID_Archive.Expr1)=[qselUniqueID_BbgDiv].[Expr2]));
When I hit Datasheet view, the relevant records are displayed but when I hit Run I get "Could not delete from specified tables". Any idea how I can change that?
Access does not work well with JOINs in a DELETE statement. You may be better off with an IN:
DELETE tblArchiveBbgDivData.*
FROM (tblArchiveBbgDivData
WHERE tblArchiveBbgDivData.ID IN
(SELECT qselUniqueID_Archive.ID
FROM qselUniqueID_Archive )
INNER JOIN qselUniqueID_BbgDiv
ON qselUniqueID_Archive.Expr1 = qselUniqueID_BbgDiv.Expr2
);
Note that your WHERE is redundant because you use the same expression in your JOIN syntax.
I have an SQL statement for a PICK sheet that returns the header/detail records for an order.
One of the fields in the SQL is basically a field to say if there are dangerous goods. If a single product on the order has a code against it, then the report should display that its hazardous.
The problem I am having is that in the SQL results, because I am putting the code on the report in the header section (and not the detail section), it is looking for the code only on the first row.
Is there a way through SQL to basically say "if one of these rows has this code, make all of these rows have this code"? I'm guessing a subselect would work here... the problem is, is that I am using a legacy system built on FoxPro and FoxPro SQL is terrible!
EDIT: just checked and I am running VFP8, subqueries in the SELECT statement were added in FVP9 :(
SELECT Header.HeaderId, Header.HeaderDescription,
Detail.DetailId, Detail.DetailDescription, Detail.Dangerous,
Danger.DangerousItems
FROM Header
INNER JOIN Detail ON Header.HeaderId = Detail.HeaderId
LEFT OUTER JOIN
(SELECT HeaderId, COUNT(*) AS DangerousItems FROM Detail WHERE Dangerous = 1 GROUP BY HeaderId) Danger ON Header.HeaderId = Danger.HeaderId
If Danger.DangerousItems > 0 then something is dangerous. If it is Null then nothing is dangerous.
If you can't do nested queries, then you should be able to create a view-like object (called a query in VFP8) for the nested select:
SELECT HeaderId, COUNT(*) AS DangerousItems FROM Detail WHERE Dangerous = 1 GROUP BY HeaderId
and then can you left join on that?
In VFP 8 and earlier, your best bet is to use three queries in a row:
SELECT Header.HeaderId, Header.HeaderDescription,
Detail.DetailId, Detail.DetailDescription, Detail.Dangerous,
Danger.DangerousItems
FROM Header
INNER JOIN Detail ON Header.HeaderId = Detail.HeaderId
INTO CURSOR csrDetail
SELECT HeaderId, COUNT(*) AS DangerousItems
FROM Detail
WHERE Dangerous
GROUP BY HeaderId
INTO CURSOR csrDanger
SELECT csrDetail.*, csrDanger.DangerousItems
FROM csrDetail.HeaderID = csrDanger.HeaderID
INTO CURSOR csrResult