Microsoft SQL Server insert from select query - sql-server

What I'm trying to do: read the logs and insert the necessary data into 3 different tables that get information from each other.
LOG_ITEM201303 is found on gamelogs db.
Mail_Item_Table, Mail_List_Table, Mail_Message_Table is found on game db.
The Mail Tables are connected via the Indexes.
CHAR_KEY, NAME, ITEMNUM are the values I need to use for my queries.
The query for me to get the data from the logs:
SELECT CHAR_KEY, NAME, ITEMNUM
FROM LOG_ITEM201303
where
(
ITEMNUM = 14317
OR ITEMNUM = 14318
OR ITEMNUM = 15478
OR ITEMNUM = 15479
OR ITEMNUM = 14301
OR ITEMNUM = 14302
OR ITEMNUM = 15476
OR ITEMNUM = 15477
OR ITEMNUM = 15018
OR ITEMNUM = 15019
OR ITEMNUM = 15020
OR ITEMNUM = 15021
OR ITEMNUM = 15022
OR ITEMNUM = 15023
OR ITEMNUM = 15024
OR ITEMNUM = 15025
OR ITEMNUM = 14437
OR ITEMNUM = 14438
OR ITEMNUM = 15656
OR ITEMNUM = 15657
OR ITEMNUM = 15658
OR ITEMNUM = 15659
OR ITEMNUM = 15660
OR ITEMNUM = 15661
OR ITEMNUM = 15662
OR ITEMNUM = 15663
) AND (KIND = 133) AND (Convert(varchar, OCCUR_TIME,111) < '2013/03/22')
Sample result of logs query above(total actual results are in 600+):
CHAR_KEY NAME ITEMNUM
-----------+----------------+-----------
28257 | clarkailey | 14438
894367 | Wolf | 15023
2869858 | HOPEINME | 14437
Now I need to automatically insert each row into this query:
CHAR_KEY NAME ITEMNUM
-----------+----------------+-----------
2869858 | HOPEINME | 14437
(this query shows an example of the 3rd sample data above being inserted...
instead of making this query for each entry is there a way for this to done faster?)
INSERT INTO Mail_Item_Table
(ItemNumber, ItemInfo, ReceiveDate)
VALUES
(14437, --this is the ITEMNUM
(SELECT CONVERT(BINARY(16), REVERSE(CONVERT(BINARY(16), 14437)))), NULL)
INSERT INTO Mail_Message_Table
(Message)
VALUES
('Automated Message from the ADMIN.')
INSERT INTO Mail_List_Table
(ReceiverCharKey, MailListIndex, MailItemIndex, MailMessageIndex, Sender, Receiver, SendDate)
VALUES
(2869858, --this is the CHAR_KEY
(SELECT TOP 1 MailListIndex+1 as last_entry
FROM Mail_List_Table
WHERE sender = 'SENDER'
ORDER BY MailListIndex DESC),
(SELECT TOP 1 MailItemIndex AS last_entry
FROM Mail_Item_Table
ORDER BY MailItemIndex DESC),
(SELECT TOP 1 MailMessageIndex AS last_entry
FROM Mail_Message_Table
ORDER BY MailMessageIndex DESC),
'SENDER',
'HOPEINME', --this is the NAME
getdate())
My question:
How to automate all this, that the query will read all the logs and insert the data row by row.
Thank you very much.
Can I use #variables for this?

You can use the following syntax for inserts
INSERT INTO dbo.Destination (Col1, Col2, Col3)
SELECT Col1, Col2, Col3
FROM dbo.Source
If you had tables with the same columns or a result set that had the same columns as your destination, you don't have to specify columns in the INSERT.
INSERT INTO dbo.Destination
SELECT *
FROM dbo.Source
Both of these are predicated on your Destination table already being created. These are NOT the same as SELECT * INTO dbo.Destination FROM dbo.Source

Related

How do I perform MAX(COUNT(*)) query?

I have a database where I have MenuItem, Item, Item_Details, and Item_Category tables. I would like to get an Item which is most frequently used in Menu.
SELECT
ItemName,
Category,
ItemPrice
FROM
restuarant.Menu_Item,
restuarant.Item,
restuarant.Item_Details,
restuarant.Item_Type
WHERE ItemId = Id_Item
AND ItemTypeId = Id_ItemType
AND ItemDetailsId = Id_ItemDetails
AND ItemId =
(SELECT ItemId
FROM restuarant.Menu_Item
HAVING COUNT(ItemId) =
(SELECT MAX(COUNT(ItemId))
FROM restuarant.Menu_Item
GROUP BY Id_MenuItem);
So the problems is I'm performing my subqueries incorrectly, I'm getting an error 'Cannot perform an aggregate function on an expression containing an aggregate or a subquery.'
How about the following:
SELECT TOP (1) ItemId, COUNT(ItemId) AS MCOUNT
FROM Menu_Item
GROUP BY ItemId
ORDER BY COUNT(ItemId) DESC
Example 1:
select aic.County, count(*) from Address_Information_County aic
group by aic.County
having count(*) = (select top 1 count(*) from Address_Information_County group by County order by count(*) desc);
Example 2:
select aic.County, count(*) from Address_Information_County aic
group by aic.County
having count(*) = (select max(cnt) from (select count(*) cnt from Address_Information_County group by County) x);
You could use "Group By" aggregate function to achieve this.
SELECT ItemID, count(*) as cnt
FROM restaurant r
GROUP BY r.ItemID
ORDER BY cnt desc
LIMIT 1;
In case, there are multiple entries that have count same as MaxCount, the following query would work.
SELECT ItemID, count(*) as cnt
FROM restaurant r
GROUP BY r.ItemID
HAVING count(*) =
(
SELECT count(*) as max_cnt
FROM restaurant r2
GROUP BY r2.ItemID
ORDER BY max_cnt desc
LIMIT 1
)
;

Subquery returned more than 1 value. How to fix it?

I have this query to show data that i want. but it gives me error [Err] 21000 - [SQL Server]Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
data : MCRX-MX023-LF-KGX, but when I enter the other data there is no error
this is Sql server 2008
SELECT
*
FROM
(
SELECT
SupplierID,
CurrencyAP AS Currency,
(
SELECT
UnitPrice
FROM
Ms_PartPriceSupplier
WHERE
SupplierID = x.SupplierID
AND PartID = x.PartID
AND LastUpdateDate = x.Tgl
) AS Price,
PartID,
(
SELECT
PartnerName
FROM
Ms_Partner
WHERE
PartnerID = x.SupplierID
) SupplierName
FROM
(
SELECT
PartID,
SupplierID,
CurrencyAP,
MAX (LastUpdateDate) AS Tgl
FROM
Ms_PartPriceSupplier
WHERE
PartID = 'MCRX-MX023-LF-KGX'
GROUP BY
PartID,
SupplierID,
CurrencyAP
) x
) y
UNION ALL
SELECT
PartnerID AS SupplierID,
'' AS Currency,
0 AS Price,
'' AS PartID,
PartnerName AS SupplierName
FROM
Ms_Partner
WHERE
PartnerID NOT IN (
SELECT DISTINCT
SupplierID
FROM
Ms_PartPriceSupplier
WHERE
PartID = 'MCRX-MX023-LF-KGX'
)
The SELECT subqueries for the Price and/or SupplierName columns in your query return multiple values. They should return only a single value (per row).
You can either provide a TOP (1) in those subqueries or adjust the conditions in their WHERE/HAVING clauses.
Some of your subqueries returns more than 1 value
SELECT
UnitPrice
FROM
Ms_PartPriceSupplier
WHERE
SupplierID = x.SupplierID
AND PartID = x.PartID
AND LastUpdateDate = x.Tgl
SELECT
PartnerName
FROM
Ms_Partner
WHERE
PartnerID = x.SupplierID
Add TOP (1) or some aggregation function like MIN, MAX in appliance with your requirements, for instance:
SELECT TOP (1)
UnitPrice
FROM
Ms_PartPriceSupplier
WHERE
SupplierID = x.SupplierID
AND PartID = x.PartID
AND LastUpdateDate = x.Tgl
SELECT TOP (1)
PartnerName
FROM
Ms_Partner
WHERE
PartnerID = x.SupplierID
The error message is quite clear. When you use a subquery in place of not a table but a value, then you must ensure only one value is returned, else you will get this error message.
Further investigation of your query reveals that you... are doing it wrong. For example,
(
SELECT
PartnerName
FROM
Ms_Partner
WHERE
PartnerID = x.SupplierID
) SupplierName
It seems here that you want to get the name that is associated with each SupplierID. You should not do subqueries in the SELECT section this way. Remember: FROM gets evaluated first, then WHERE, then SELECT. What you actually instructed the database here is to try to return a SINGLE value as SupplierName: this will only work if your query only has one SupplierID.
You need to start thinking with joins. Here is how you should write your query:
SELECT
*
FROM
(
SELECT
SupplierID,
CurrencyAP AS Currency,
Ms_PartPriceSupplier.UnitPrice AS Price,
PartID,
Ms_Partner.PartnerName as SupplierName
FROM
(
SELECT
PartID,
SupplierID,
CurrencyAP,
MAX (LastUpdateDate) AS Tgl
FROM
Ms_PartPriceSupplier
WHERE
PartID = 'MCRX-MX023-LF-KGX'
GROUP BY
PartID,
SupplierID,
CurrencyAP
) x
inner join Ms_Partner on PartnerID = x.SupplierID
inner join Ms_PartPriceSupplier on SupplierID = x.SupplierID AND PartID = x.PartID AND LastUpdateDate = x.Tgl
) y
UNION ALL
SELECT
PartnerID AS SupplierID,
'' AS Currency,
0 AS Price,
'' AS PartID,
PartnerName AS SupplierName
FROM
Ms_Partner
WHERE
PartnerID NOT IN (
SELECT DISTINCT
SupplierID
FROM
Ms_PartPriceSupplier
WHERE
PartID = 'MCRX-MX023-LF-KGX'
)

How to test against a list of items in an if statement

I have a large table (130 columns). It is a monthly dataset that is separated by month (jan,feb,mar,...). every month I get a small set of duplicate rows. I would like to remove one of the rows, it does not matter which row to be deleted.
This query seems to work ok when I only select the ID that I want to filter the dups on, but when I select everything "*" from the table I end up with all of the rows, dups included. My goal is to filter out the dups and insert the result set into a new table.
SELECT DISTINCT a.[ID]
FROM MonthlyLoan a
JOIN (SELECT COUNT(*) as Count, b.[ID]
FROM MonthlyLoan b
GROUP BY b.[ID])
AS b ON a.[ID] = b.[ID]
WHERE b.Count > 1
and effectiveDate = '01/31/2017'
Any help will be appreciated.
This will show you all duplicates per ID:
;WITH Duplicates AS
(
SELECT ID
rn = ROW_NUMBER() OVER (PARTITION BY ID ORDER BY ID)
FROM MonthlyLoan
)
SELECT ID,
rn
FROM Duplicates
WHERE rn > 1
Alternatively, you can set rn = 2 to find the immediate duplicate per ID.
Since your ID is dupped (A DUPPED ID!!!!)
all you need it to use the HAVING clause in your aggregate.
See the below example.
declare #tableA as table
(
ID int not null
)
insert into #tableA
values
(1),(2),(2),(3),(3),(3),(4),(5)
select ID, COUNT(*) as [Count]
from #tableA
group by ID
having COUNT(*) > 1
Result:
ID Count
----------- -----------
2 2
3 3
To insert the result into a #Temporary Table:
select ID, COUNT(*) as [Count]
into #temp
from #tableA
group by ID
having COUNT(*) > 1
select * from #temp

Uisng exists in sql to find duplicates, is there a cleaner way?

See script below to find duplicates in SQL Server DB. Is there a cleaner way?
select itemnum
from matusetrans a
where exists (select null
from matusetrans b
where a.itemnum = b.itemnum
and a.actualdate = b.actualdate
and a.matusetransid != b.matusetransid
and (a.rotassetnum = b.rotassetnum
or (a.rotassetnum is null and b.rotassetnum is null))
and a.quantity = b.quantity)
group by itemnum
You could try:
SELECT itemnum
FROM matusetrans
GROUP BY [ColumnNames]
HAVING
COUNT(*) > 1
Assuming you want to find duplicate itemnum in table,Please use below query
SELECT itemnum
FROM matusetrans
GROUP BY [ItemNum]
HAVING COUNT(ItemNum) > 1
Using HAVING COUNT(*) > 1 may give you result as all are distinct if there are any Datetime columns like order datetime which generally varies per record.
Thanks,
Sree
Another possibility (but not neccessarily "cleaner") might be
WITH cte AS(
SELECT columns, ROW_NUMBER() OVER (PARTITION BY columns ORDER by columns) AS RowIdx
FROM matusetrans
GROUP BY columns
)
SELECT *
FROM cte
WHERE RowIdx > 1

select top 1 with a group by

I have two columns:
namecode name
050125 chris
050125 tof
050125 tof
050130 chris
050131 tof
I want to group by namecode, and return only the name with the most number of occurrences. In this instance, the result would be
050125 tof
050130 chris
050131 tof
This is with SQL Server 2000
I usually use ROW_NUMBER() to achieve this. Not sure how it performs against various data sets, but we haven't had any performance issues as a result of using ROW_NUMBER.
The PARTITION BY clause specifies which value to "group" the row numbers by, and the ORDER BY clause specifies how the records within each "group" should be sorted. So partition the data set by NameCode, and get all records with a Row Number of 1 (that is, the first record in each partition, ordered by the ORDER BY clause).
SELECT
i.NameCode,
i.Name
FROM
(
SELECT
RowNumber = ROW_NUMBER() OVER (PARTITION BY t.NameCode ORDER BY t.Name),
t.NameCode,
t.Name
FROM
MyTable t
) i
WHERE
i.RowNumber = 1;
select distinct namecode
, (
select top 1 name from
(
select namecode, name, count(*)
from myTable i
where i.namecode = o.namecode
group by namecode, name
order by count(*) desc
) x
) as name
from myTable o
SELECT max_table.namecode, count_table2.name
FROM
(SELECT namecode, MAX(count_name) AS max_count
FROM
(SELECT namecode, name, COUNT(name) AS count_name
FROM mytable
GROUP BY namecode, name) AS count_table1
GROUP BY namecode) AS max_table
INNER JOIN
(SELECT namecode, COUNT(name) AS count_name, name
FROM mytable
GROUP BY namecode, name) count_table2
ON max_table.namecode = count_table2.namecode AND
count_table2.count_name = max_table.max_count
I did not try but this should work,
select top 1 t2.* from (
select namecode, count(*) count from temp
group by namecode) t1 join temp t2 on t1.namecode = t2.namecode
order by t1.count desc
Here are to examples that you could use but the temp table use is more efficient than the view, but was done on a small data sample. You would want to check your own statistics.
--Creating A View
GO
CREATE VIEW StateStoreSales AS
SELECT t.state,t.stor_id,t.stor_name,SUM(s.qty) 'TotalSales'
,ROW_NUMBER() OVER (PARTITION BY t.state ORDER BY SUM(s.qty) DESC) AS 'Rank'
FROM [dbo].[sales] s
JOIN [dbo].[stores] t ON (s.stor_id = t.stor_id)
GROUP BY t.state,t.stor_id,t.stor_name
GO
SELECT * FROM StateStoreSales
WHERE Rank <= 1
ORDER BY TotalSales Desc
DROP VIEW StateStoreSales
---Using a Temp Table
SELECT t.state,t.stor_id,t.stor_name,SUM(s.qty) 'TotalSales'
,ROW_NUMBER() OVER (PARTITION BY t.state ORDER BY SUM(s.qty) DESC) AS 'Rank' INTO #TEMP
FROM [dbo].[sales] s
JOIN [dbo].[stores] t ON (s.stor_id = t.stor_id)
GROUP BY t.state,t.stor_id,t.stor_name
SELECT * FROM #TEMP
WHERE Rank <= 1
ORDER BY TotalSales Desc
DROP TABLE #TEMP

Resources