SQL Server: select has too many columns for insert - sql-server-2000

I'm trying to run this query and I keep getting this error:
The select list for the INSERT statement contains more items than the insert list. The number of SELECT values must match the number of INSERT columns.
This error comes after I try doing INSERT INTO #tempTable SELECT.... It worked just fine when I had only 2 columns for each temp table, but now that I've added a third, it keeps giving me this error even though it appears to be selecting 3 columns to insert into the table with 3 columns.
The query overall is trying to get a few column values, (customer ids, contacts, and a salesman id) over different tables, but the problems have come from needing to root out duplicate customer IDs and making sure that only 1 salesman and 1 contact showing up for each customer. If it wasn't for the salemen id, the query would work perfectly. Here is what I have so far:
if object_id('tempdb..#tempTable') IS NOT NULL DROP TABLE #tempTable
if object_id('tempdb..#tempTable2') IS NOT NULL DROP TABLE #tempTable2
CREATE TABLE #tempTable(
CustomerID int,
ContactName nvarchar(50),
SalesmenID nvarchar(4)
)
CREATE TABLE #tempTable2(
CustomerID int,
ContactName nvarchar(50),
SalesmenID nvarchar(4)
)
INSERT INTO #tempTable
(CustomerID, ContactName,SalesmenID)
SELECT Customers.[Customer ID],Salesmen.[4 Letter ID],
CASE([Customer Contact].defaultprintonorder)
WHEN 0
THEN 'zzzzzzz_NOCONTACT'
ELSE
[Customer Contact].[Contact Name]
END as ContactName
From Customers
LEFT JOIN [Customer Contact] on Customers.[Customer ID]=[Customer Contact].[Customer ID]
Left Join [Customer Salesmen] On Customers.[Customer ID]=[Customer Salesmen].[Customer ID]
INNER JOIN Salesmen on [Customer Salesmen].[Salesman Name]=Salesmen.[Salesman Name]
WHERE Customers.[Customer ID] NOT IN(SELECT CustomerID FROM #tempTable)
GROUP BY Customers.[Customer ID], [Contact Name], DefaultPrintOnOrder
INSERT INTO #tempTable2 (CustomerID, ContactName,SalesmenID)
SELECT distinct CustomerID, '', SalesmenID FROM #tempTable
UPDATE #TempTable2 SET
#tempTable2.CustomerID=#tempTable.CustomerID,
#tempTable2.ContactName=#tempTable.ContactName
FROM
#TempTable2
INNER JOIN #TempTable ON #TempTable2.CustomerID=#TempTable.CustomerID
SELECT Salesmen.[4 Letter ID],
[Customers].[Customer ID],
[Customer Contact].[Contact Name]
FROM Customers
Right JOIN #TempTable2 ON
Customers.[Customer ID]=#TempTable2.CustomerID
Right JOIN [Customer Salesmen] ON
#TempTable2.CustomerID=[Customer Salesmen].[Customer ID]
INNER JOIN
[Salesmen] ON
[Customer Salesmen].[Salesman Name]=Salesmen.[Salesman Name]
LEFT JOIN
[Customer Contact] ON
#TempTable2.[CustomerID]=[Customer Contact].[Customer ID]
EDIT:
I added SalesmenID to the inserts, but now I'm getting this error message 3 times:
Invalid column name 'SalesmenID'.
It comes up once for the temptable insert and twice for the temptable2 insert

You're trying to store 3 values (Customers.[Customer ID], Salesmen.[4 Letter ID], ContactName) in 2 fields (CustomerID, ContactName)
INSERT INTO #tempTable
(CustomerID, ContactName)
SELECT Customers.[Customer ID],Salesmen.[4 Letter ID],
CASE([Customer Contact].defaultprintonorder)
WHEN 0
THEN 'zzzzzzz_NOCONTACT'
ELSE
[Customer Contact].[Contact Name]
END as ContactName

Are you sure the problem is where you indicated?
This insert has 2 destination columns and 3 select columns:
INSERT INTO #tempTable
(CustomerID, ContactName) -- 2 columns
SELECT Customers.[Customer ID], --column 1
Salesmen.[4 Letter ID], --column 2
CASE([Customer Contact].defaultprintonorder) -- column 3!
WHEN 0
THEN 'zzzzzzz_NOCONTACT'
ELSE
[Customer Contact].[Contact Name]
END as ContactName
From Customers...

Related

does Left Join in SQL not shows matching value in second table? [duplicate]

This question already has answers here:
Isn't SQL A left join B, just A?
(5 answers)
Closed 1 year ago.
I see below question and I believe it is false but the correct answer is true.
A left outer join on tables CUSTOMER and AGENT, with
CUSTOMER being listed first and AGENT being listed
second in the SQL command, yields all of the rows in the
CUSTOMER table, including those that do not have a
matching value in the AGENT table.
Based on above question, it should be below select:
select C.*, A.*
from Customer C
left join Agent A on A.CID = C.CID
So the result of the above Statement is all rows from Customer table + matching values in Customer and Agent table. (My Professor says the True/False question is correct but it seems false).
If you try it you will easily see that the statement quoted is TRUE. When no matching row exists in the agent table, the customer row is still shown e.g. Customer 2 below.
declare #Customer table (id int, [Name] varchar(32));
declare #Agent table (id int, CustomerId int, [Name] varchar(32));
insert into #Customer (id, [Name])
values
(1, 'Test Customer 1'),
(2, 'Test Customer 2');
insert into #Agent (id, CustomerId, [Name])
values
(1, 1, 'Test Agent 1');
select C.id [Customer id], C.[Name] [Customer Name], A.id [Agent id], A.CustomerId [Agent Customer id], A.[Name] [Agent Name]
from #Customer C
left join #Agent A on A.CustomerId = C.id;
Results
Customer id
Customer Name
Agent id
Agent Customer id
Agent Name
1
Test Customer 1
1
1
Test Agent 1
2
Test Customer 2
NULL
NULL
NULL
And as The Impaler points out, you can get duplicate Customer rows if there exist multiple Agents per customer e.g. if you append the following SQL to that which we already have:
insert into #Agent (id, CustomerId, [Name])
values
(2, 1, 'Test Agent 2');
You get
Customer id
Customer Name
Agent id
Agent Customer id
Agent Name
1
Test Customer 1
1
1
Test Agent 1
1
Test Customer 1
2
1
Test Agent 2
2
Test Customer 2
NULL
NULL
NULL

How to include cash entry

Below is my SCHEMA with create scripts:
CREATE TABLE transaction
(tran_id INT,
tran_seq_nbr INT,
Tran_sold_amt INT,
Card_no VARCHAR(20),
Payment_Method VARCHAR(20),
Card_type VARCHAR(20),
Tran_Date VARCHAR(20));
Insert into transaction Table:
INSERT INTO transaction (tran_id, tran_seq_nbr,Tran_sold_amt, Card_no,
Payment_Method, Card_type, Tran_Date)
VALUES(1010,1,10,'123','Card','Visa', '2019-01-01'),
(1010,2,20,'124','Card','MasterCard', '2019-01-01'),
(2020,1,30,'125','Card','Visa', '2019-01-31'),
(2020,2,40,Null,'Cash',Null,'2019-01-31'),
(10101,1,100,'123','Card','Visa','2019-02-01'),
(1011,1,100,Null,'Cash',Null,'2019-02-01');
CREATE TABLE Customer(Cust_id INT, Cust_name VARCHAR(20));
INSERT INTO Customer (Cust_id,Cust_name)
VALUES(1,'JANE DOE'),
(2,'JOHN DOE');
CREATE TABLE Credit_card (Card_no INT, Cust_id INT, Card_type VARCHAR(20));
INSERT INTO Credit_card (Card_no,Cust_id,Card_type)
VALUES(123,1,'Visa'),
(124,1,'MasterCard'),
(125,2,'Visa'),
(126,2,'MasterCard'),
(127,3,'Visa'),
(128,4,'American Express');
My SOLUTION is below
Select customer.cust_name, customer.cust_id, credit_card.card_type,
credit_card.card_no,sum(transaction.Tran_sold_amt) AS AMOUNT,
YEAR (transaction.tran_date) AS YEAR
from customer
join credit_card
on customer.cust_id=credit_card.cust_id
join transaction
on credit_card.card_no = transaction.card_no
group by credit_card.card_type, credit_card.card_no, YEAR,customer.cust_name;
My PROBLEM is:
I am not able to find the cash entry rest of the entries are visible
Please help is with the fix and thanks.
Welcome to SO!.
The thing is your are using a so called INNER join, meaning that it only show the records that are related.
Your Cash entries are not linked to the Credit_Card table, so they will not be shown. If you want to retrieve them as well, you could use this:
SELECT [Transaction].[Payment_Method]
,ISNULL([Transaction].Card_type,'') AS [Card Type]
,ISNULL(credit_card.card_no,'') AS [Card Number]
,SUM(ISNULL([transaction].Tran_sold_amt,0)) AS AMOUNT
,YEAR([Transaction].tran_date) AS [YEAR]
,ISNULL(Customer.Cust_name,'') AS [Customer Name]
FROM [transaction]
LEFT OUTER JOIN credit_card
on credit_card.card_no = [transaction].card_no
LEFT OUTER JOIN [Customer]
on customer.cust_id=credit_card.cust_id
GROUP BY [Transaction].[Payment_Method]
,[Transaction].Card_type
,credit_card.card_type
,credit_card.card_no
,YEAR([transaction].tran_date)
,customer.Cust_id
,customer.cust_name;
By the way, this is T-SQL.
I used OUTER JOIN, so that all records from the transaction table are used, even if they are not related to the other 2 tables.

get values from master table based on fields in sqlserver

I want to retrieve the values from master table based on transaction table different col value,
My master table will have username,FirstName,lastName.
My transaction table will have Id,CreatedUser,UpdatedUser.
So I want query to get report from sql server ,get FirstName,lastName from master table for createruser and get FirstName,lastName from master table for updateuser.
Ex:
Master Table
User ID First Name Last Name
cer001 Ds CV
cer002 vb av
Transaction Table
id CreatedUser UdatedUser
2323 cer001 cer002
So Report should get the results like
Id CreatedUser UpdatedUSer
2323 Ds,CV Vb,av
it should be performance wise also good. Please help how to get this
You are looking for self join
select
t.Id, m.FirstName +','+m.LastName as CreatedUser,
mm.FirstName +','+mm.LastName as UpdatdUser
from Master m
inner join Transaction t on t.CreatedUser = m.[User ID]
inner join Master mm on mm.[User ID]= t.UpdatedUser
You should try left join from Transaction table to master table.
LEFT to take care of any NULL values
see working demo
Query will be
create table [Master] ([User ID] varchar(10), [First Name] varchar(10), [Last Name] varchar(10));
insert into [Master] values
('cer001','Ds','CV'),('cer002','vb','av')
create table [Transaction] (id int, CreatedUser varchar(10),UpdatedUser varchar(10))
insert into [Transaction] values
(2323, 'cer001','cer002');
select
ID=T.id,
CreatedUser= ISNULL (M1.[First Name],'')+ ','+ISNULL(M1.[Last Name],'' ),
UpdatedUser= ISNULL (M2.[First Name],'')+ ','+ISNULL(M2.[Last Name],'')
from
[Transaction] T
LEFT JOIN
[Master] M1
ON T.CreatedUser =M1.[User ID]
LEFT JOIN
[Master] M2
ON T.UpdatedUser =M2.[User ID]
Maybe you can try using sub query as below
Select
t.id,
(Select TOP 1 Rtrim(m.[First Name])+','+RTRIM(m.[Last Name]) from [Master] m where m.[User ID] = t.CreatedUser) as CreatedUser,
(Select TOP 1 Rtrim(m.[First Name])+','+RTRIM(m.[Last Name]) from [Master] m where m.[User ID] = t.UpdatedUser) as UpdatedUser
from [Transaction] t

Sum on columns with the same ID and different columns?

Using Microsoft SQL Server
I need to create a table that takes the User IDs from the temp table. Collects only those User IDs and then adds all of the Points for that individual user together.
Temp table which pulled all the most recent records for each User ID.
User ID | Points | Date Field
-----------------------------
1 1 10/31/2016
3 1 08/26/2016
Main
User ID | Points | Date Field | Other Field
--------------------------------------------
1 1 10/31/2016 N/A
1 2 10/25/2016 N/A
1 3 09/18/2016 N/A
2 1 08/17/2017 N/A
2 16 07/11/2017 N/A
3 1 08/27/2016 N/A
3 5 05/14/2016 N/A
So take temp table and match those User IDs to the main table. From that data you should only have collected those which match the record IDs in the temp table. From there the report will then be broken down to look like below. Which shows the most recent date, and a sum of all the points for that User ID.
User ID | Points | Date Field | Other Field
---------------------------------------------
1 6 10/31/2016 N/A
3 6 08/27/2016 N/A
I tried this SQL:
SELECT
a.[User ID], a.[Points], a.[Date Field], a.[Other Field1], a.[Other Field2], a.[Other Field3],
(CASE WHEN b.[User ID] = a.[User ID] THEN SUM(a.Points) END) AS [Total Points]
FROM
Main_Table a
INNER JOIN
#Temp b ON b.[User ID] = a.[User ID]
GROUP BY
a.[User ID], [Points], [Date Field], [Other Field1], [Other Field2], [Other Field3]
I get the total points column, but is not adding all the fields with identical User IDs together.
I just need to know where I am going wrong. I'm not the best with SQL and I'm still learning. Please understand I am trying my best to figure this out.
Thank you!
I imagine something like this is what you're looking for:
SELECT
b.[User ID]
, b.[Points]
, b.[Date Field]
, SUM(a.Points) [Total Points]
FROM
#Temp b
INNER JOIN Main_Table a ON b.[User ID] = a.[User ID]
GROUP BY
b.[User ID]
, b.[Points]
, b.[Date Field]
But then the question would be, which of the other fields from Main_Table do you want to keep?
I imagine possibly something like this:
SELECT
b.[User ID]
, b.[Points]
, b.[Date Field]
, m.[Other_Field] -- etc.
, SUM(a.Points) [Total Points]
FROM
#Temp b
INNER JOIN Main_Table m ON
b.[User ID] = m.[User ID]
AND b.[Date Field] = m.[Date Field]
INNER JOIN Main_Table a ON b.[User ID] = a.[User ID]
GROUP BY
b.[User ID]
, b.[Points]
, b.[Date Field]
, m.[Other_Field]
To get Sum, you have to group by fields that are non-changing. So User ID is the non-changing field you would want to SUM by. The group by is done to this non-aggregate field User ID. The problem with date and [Other Field] is that they are changing often. This defeats the group by. You have to query back to the original table to get the max date field if that's your intent. I'm not sure what [Other Field] are, but you have to take into account if they are different changing values.
SELECT dT.[User ID]
,dT.Points
,(SELECT MAX([Date Field])
FROM #main M2
WHERE M2.[User ID] = dT.[User ID]) AS [Date Field]
FROM (
SELECT M.[User ID]
,SUM(M.Points) AS Points
FROM #main M
WHERE [User ID] IN (SELECT [User ID] FROM #temp)
GROUP BY M.[User ID]
) AS dT
Creates output:
User ID Points Date Field
1 6 2016-10-31
3 6 2016-08-27
I assume this should help
--======================= CREATE TEMP TABLE==============================
CREATE TABLE #TEMP ([USER ID] INT,
POINTS INT,
[DATE FIELD] DATE)
--======================= VALUES ON THE TABLE ===============================
INSERT INTO #TEMP VALUES ( 1 ,1,'10-31-2016')
INSERT INTO #TEMP VALUES (3,1,'08-26-2016')
--======================== CREATE MAIN TABLE ============================
CREATE TABLE #MAIN ([USER ID] INT,
POINTS INT,
[DATE FIELD] DATE,
[OTHER FIELD] NVARCHAR(50))
--======================= VALUES ON MAIN TABLE===================
INSERT INTO #MAIN VALUES ( 1,1,'10-31-2016','N/A')
INSERT INTO #MAIN VALUES ( 1,2,'10-25-2016','N/A')
INSERT INTO #MAIN VALUES ( 1,3,'09-18-2016','N/A')
INSERT INTO #MAIN VALUES ( 2,1,'08-17-2017','N/A')
INSERT INTO #MAIN VALUES ( 2,16,'07-11-2017','N/A')
INSERT INTO #MAIN VALUES ( 3,1,'08-27-2016','N/A')
INSERT INTO #MAIN VALUES ( 3,5,'05-14-2016','N/A')
--=====GETTING SUM OF YOUR POINTS=====
SELECT T2.[USER ID],
SUM(T1.[POINTS]) AS [TOTAL POINT],
T2.[DATE FIELD],
T1.[OTHER FIELD]
FROM #MAIN AS T1
RIGHT JOIN #TEMP AS T2
ON T1.[USER ID] = T2.[USER ID]
GROUP BY T2.[USER ID],
T2.[DATE FIELD],
T1.[OTHER FIELD]
DROP TABLE #TEMP
DROP TABLE #MAIN

How do I insert records from one table to another when some records don't fit a FK constraint?

I have a source table that has 10,000 records that I want to insert into a destination table. The insert would also include an ID field. There is a third table with a foreign key relationship on the id field. How do I insert the records that have the correct ids for the FK and skip the ones that don't have the correct ids for the FK?
Set IDENTITY_INSERT Destination ON
GO
INSERT INTO [dbo].[Destination]
(
Id,
[Street1]
,[Street2]
,[City]
,[State]
,[PostalCode]
,[ContactId]
,[Institution_ID]
,[LegacyIDNumber]
)
SELECT DISTINCT
[Account Number],
[Address],
[Address 2],
[City],
Left([State],2),
[Postal Code],
[Account Number],
[Account Number],
[Account Number]
FROM [dbo].[Source]
GO
Set IDENTITY_INSERT Destination OFF
GO
The error I get is
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_dbo.Destination_dbo.Contacts_ContactId". The conflict occurred in database "xxxx", table "dbo.Contacts", column 'Id'.
The statement has been terminated.
You could add an INNER JOIN to the Contacts table to ensure that the [Account Number] from the source matches the Id in the Contacts table. Anything that doesn't match would get filtered out which should keep you from getting the error about the FK constraint.
SELECT [Account Number],
[Address],
[Address 2],
[City],
Left([State],2),
[Postal Code],
[Account Number],
[Account Number],
[Account Number]
FROM [dbo].[Source]
INNER JOIN dbo.Contacts ON Contacts.id=Source.[Account Number]
There is probably a query hint or some other database trick that would allow you to pull this off more properly. But AFAIK the above should work.