Error while posting to a table - sql

Platform used:
SQL Server 2008 and C++ Builder
I am doing an inner join between 2 tables which was giving me an error:
Row cannot be located for updating
Query:
SELECT DISTINCT
b.Acc, b.Region, b.Off, b.Sale, a.OrgDate
FROM
sales b
INNER JOIN
dates a ON (a.Acc = b.Acc and a.Region = b.Region and a.year= b.year)
WHERE
(a.xdate <> a.yDate)
and (b.Sale = a.SaleDate)
and b.year = 2010
Note: Acc, Region, Off are primary keys of table b and are also present in table a.
Table a has an id which is the primary key which does not appear in the query.
It turned out that my inner join was returning duplicate rows.
I changed my inner join query to use 'DISTINCT' so that only distinct rows are returned and not duplicate. The query runs but then I get the error:
Insufficient key column information for updating or refreshing.
It does turn out that the fields which are primary keys in Table A have the same names as the fields in Table B
I found that this is a bug which occurs while updating ADO record-sets.
BUG: Problem Updating ADO Hierarchical Recordset When Join Tables Share Same Column Name
I have the following 2 questions:
Is it not a good idea to use Distinct on an inner join query?
Has anyone found a resolution for that bug associated with TADO Query's?
Thank you,

The way I would solve this is to construct an update query by hand and run it through TADOQuery.ExecSQL. That assumes you actually know what you are doing.
The question is WHY are you working on a recordset that results in multiples of the same row, on all fields? You should be inspecting your query and fixing it. DISTINCT doesn't help, because SQL Server has picked one record but ADO won't know which one it picked, since there isn't enough information to properly identify the source on each side of the JOIN.
This query pulls in a.id to make the source records identifiable:
SELECT Acc,Region,Off,Sale,OrgDate,id
FROM
(
SELECT b.Acc,b.Region,b.Off,b.Sale,a.OrgDate, a.id,
rn=row_number() over (partition by b.Acc,b.Region,b.Off order by a.id asc)
FROM sales b
JOIN dates a ON(a.Acc = b.Acc and a.Region = b.Region and a.year= b.year)
WHERE a.xdate <> a.yDate
and b.Sale = a.SaleDate
and b.year = 2010
) X
WHERE rn=1;
Not tested, but it should work with ADO

Related

Compare 2 Tables and write RowID from Table A to Table B

I have Table A with RowID, Date, Vendor and Cost, Confirmed
I have table B with RowID, Date, Vendor and Cost, Confirmed
Table A list our purchases.
Table B list the statement data from the credit card.
I would like to compare Date, Vendor and Cost in Table A with the same columns in Table B. If there is a match with those three columns, then I would like to take the RowID value from Table A and write it to the matching row in Table B under the Confirmation column.
I am very new to SQL and I am not even sure this is a reasonable expectation.
What do you think?
Is this enough detail to provide your opinion?
Thank you for any help you can give.
Currently I am using an Outer Right Join to get all the rows that do NOT have a match. What I really need is the opposite.
It might help to know what database engine you are using...
My answers are going to relate to MS SQL Server, but much SQL Syntax is the same...
To answer your first question, I would write something like:
Update TableB Set Confirmation = TableA.RowID From TableA
Where TableA.Vendor = TableB.Vendor
And TableA.Cost = TableB.Cost
And TableA.Date = TableB.Date
I would use aliases, but I left them out to hopefully make it easier to understand.
To answer your second question, you can specify an INNER JOIN which is the opposite of an OUTER JOIN and as you mentioned, what you are looking for, as it will return ALL rows that Match and exclude the rest.
You can do this with this query
UPDATE
B
SET
Confirmation = A.RowID
FROM
TableA A
INNER JOIN TableB B
ON B.Vendor = A.Vendor
AND B.Cost = A.Cost
AND B.Date = A.Date
Basically we do an inner join to keep the intersection (the records that match) of the two tables. and update the records that coincided from table B with the id of table A

Issue with joins in a SQL query

SELECT
c.ConfigurationID AS RealflowID, c.companyname,
c.companyphone, c.ContactEmail, COUNT(k.caseid)
FROM
dbo.Configuration c
INNER JOIN
dbo.cases k ON k.SiteID = c.ConfigurationId
WHERE
EXISTS (SELECT * FROM dbo.RepairEstimates
WHERE caseid = k.caseid)
AND c.AccountStatus = 'Active'
AND c.domainid = 46
GROUP BY
c.configurationid,c.companyname, c.companyphone, c.ContactEmail
I have this query - I am using the configuration table to get the siteid of the cases in the cases table. And if the case exists in the repair estimates table pull the company details listed and get a count of how many cases are in the repair estimator table for that siteid.
I hope that is clear enough of a description.
But the issue here is the count is not correct with the data that is being pulled. Is there something I could do differently? Different join? Remove the exists add another join? I am not sure I have tried many different things.
Realized I was using the wrong table. The query was correct.

Getting way more results than expected in SQL left join query

My code is such:
SELECT COUNT(*)
FROM earned_dollars a
LEFT JOIN product_reference b ON a.product_code = b.product_code
WHERE a.activity_year = '2015'
I'm trying to match two tables based on their product codes. I would expect the same number of results back from this as total records in table a (with a year of 2015). But for some reason I'm getting close to 3 million.
Table a has about 40,000,000 records and table b has 2000. When I run this statement without the join I get 2,500,000 results, so I would expect this even with the left join, but somehow I'm getting 300,000,000. Any ideas? I even refered to the diagram in this post.
it means either your left join is using only part of foreign key, which causes row multiplication, or there are simply duplicate rows in the joined table.
use COUNT(DISTINCT a.product_code)
What is the question are are trying to answer with the tsql?
instead of select count(*) try select a.product_code, b.product_code. That will show you which records match and which don't.
Should also add a where b.product_code is not null. That should exclude the records that don't match.
b is the parent table and a is the child table? try a right join instead.
Or use the table's unique identifier, i.e.
SELECT COUNT(a.earned_dollars_id)
Not sure what your datamodel looks like and how it is structured, but i'm guessing you only care about earned_dollars?
SELECT COUNT(*)
FROM earned_dollars a
WHERE a.activity_year = '2015'
and exists (select 1 from product_reference b ON a.product_code = b.product_code)

Duplicate columns with inner Join

SELECT
dealing_record.*
,shares.*
,transaction_type.*
FROM
shares
INNER JOIN shares ON shares.share_ID = dealing_record.share_id
INNER JOIN transaction_type ON transaction_type.transaction_type_id = dealing_record.transaction_type_id;
The above SQL code produces the desired output but with a couple of duplicate columns. Also, with incomplete display of the column headers. When I change the
linesize 100
the headers shows but data displayed overlaps
I have checked through similar questions but I don't seem to get how to solve this.
You have duplicate columns, because, you're asking to the SQL engine for columns that they will show you the same data (with SELECT dealing_record.* and so on) , and then duplicates.
For example, the transaction_type.transaction_type_id column and the dealing_record.transaction_type_id column will have matching rows (otherwise you won't see anything with an INNER JOIN) and you will see those duplicates.
If you want to avoid this problem or, at least, to reduce the risk of having duplicates in your results, improve your query, using only the columns you really need, as #ConradFrix already said. An example would be this:
SELECT
dealing_record.Name
,shares.ID
,shares.Name
,transaction_type.Name
,transaction_type.ID
FROM
shares
INNER JOIN shares ON shares.share_ID = dealing_record.share_id
INNER JOIN transaction_type ON transaction_type.transaction_type_id = dealing_record.transaction_type_id;
Try to join shares with dealing_record, not shares again:
select dealing_record.*,
shares.*,
transaction_type.*
FROM shares inner join dealing_record on shares.share_ID = dealing_record.share_id
inner join transaction_type on transaction_type.transaction_type_id=
dealing_record.transaction_type_id;

Oracle updating table based on a join

I have two tables
table 1 : rm_example(customer, weekno, salenum, card_type,...., imputed)
table 2 : rm_dummy(customer, weekno, imputed)
The imputed column in table one is null(all columns).
I want to set "imputed" column in table 1 with the value of "imputed" in table two where customer and weekno match....
below the query I wrote.....but it is taking forever to execute...
update rm_example e
set e.imputed =
(select imputed
from rm_dummy d
inner join rm_example e on e.customer=d.customer and e.weekno=d.weekno)...
Is something wrong with the query?
I am working on remote database using sqldeveloperplus...and we are talking about million rows.
MERGE is usually quite a bit faster than an UPDATE with a subquery (the syntax might seem a little bit weird, but you'll get used to it); this assumes rm_example has a primary key column PK:
MERGE INTO rm_example target
USING
(SELECT e.pk as e_pk,
d.imputed
FROM rm_dummy d
INNER JOIN rm_example e ON e.customer=d.customer AND e.weekno=d.weekno) src
ON (target.pk = src.e_pk)
WHEN MATCHED THEN UPDATE
SET target.imputed = src.imputed;
Not sure if it will be faster than what you have done already but you try this
UPDATE
(SELECT e.imputed, d.imputed
FROM rm_example e
INNER JOIN rm_dummy d ON e.customer = d.customer AND e.weekno = d.weekno)
SET e.imputed = d.imputed;
After reading 8 Bulk Update Methods Compared (Oracle) I see this is really a Deprecated method that a MERGE syntax should be used. But in saying that depending on your system this could possibly have better performance