Create table from query result - sql-server

I do have a problem with creating proper SQL statement.
Scenario, i do have a table "Excel" which is populated by SQLBulkCopy few times, after that table contains duplicates which I want to sum by "Buildneed", I have figured out way to return "consolidated" result with below query :
SELECT GBC, Description, sum(Buildneed) as Buildneed, Replaced
FROM Excel
GROUP BY GBC, Description, Replaced
ORDER BY GBC ASC
Now I would like to drop NewTable if exists, create NewTable again and populate this table from mentioned above result.
So I wrote this statement :
DROP TABLE IF EXISTS dbo.NewTable
CREATE TABLE [dbo].[NewTable]
(
[GBC] INT NULL,
[Description] VARCHAR (80) NULL,
[Buildneed] INT NULL,
[Replaced] VARCHAR (80) NULL
);
SELECT Excel2.GBC, Excel2.Description, Excel2.Buildneed, Excel2.Replaced
INTO NewTable
FROM (SELECT GBC, Description, sum(Buildneed) as Buildneed, Replaced
FROM Excel
GROUP BY GBC, Description, Replaced
ORDER BY GBC ASC) AS Excel2
I'm not receiving any error information, table is not created after running above query.
Every single time new data will come to table "Excel" I want to "consolidate -> drop NewTable -> create NewTable with new data"
Sample data :
CREATE TABLE [dbo].[Excel]
(
[GBC] INT NULL,
[Description] VARCHAR (80) NULL,
[Buildneed] INT NULL,
[Replaced] VARCHAR (80) NULL
);
INSERT INTO #Excel (GBC, [Description], Buildneed, Replaced)
SELECT 71744, 'RES_TF,10k,0402,1%,0,1W,100PPM/C', 2000
UNION ALL
SELECT 71744, 'RES_TF,10k,0402,1%,0,1W,100PPM/C', 1000
UNION ALL
SELECT 76527, 'CAP_CER,10nF,0402,10%,50V,X7R', 288
UNION ALL
SELECT 86911, 'CAP_CER,10nF,0603,10%,100V,X7R', 1464
Expected result -> New table created with name "NewTable"
GBC / Description / Buildneed / Replaced
71744 / RES_TF,10k,0402,1%,0,1W,100PPM/C / **3000** / null
76527 / CAP_CER,10nF,0402,10%,50V,X7R / 288 / null
86911 / CAP_CER,10nF,0603,10%,100V,X7R / 1463 / null

First of all, I suggest to create the new table with another name, drop the old table after the new table has successfully been created and then rename the new table to the desired name - so you prevent data loss in case anything doesn't work during table creation. Furthermore the SELECT ... INTO should create a new table without the need of creating it first. Another possibility would be INSERT INTO... SELECT...
Here an example:
CREATE TABLE [dbo].[Excel] (
[GBC] INT NULL,
[Description] VARCHAR (80) NULL,
[Buildneed] INT NULL,
[Replaced] VARCHAR (80) NULL
);
insert into [Excel] (GBC, [Description], Buildneed, Replaced)
select 71744, 'RES_TF,10k,0402,1%,0,1W,100PPM/C' ,2000, NULL
union all
select 71744, 'RES_TF,10k,0402,1%,0,1W,100PPM/C' ,1000, NULL
union all
select 76527, 'CAP_CER,10nF,0402,10%,50V,X7R' ,288, NULL
union all
select 86911, 'CAP_CER,10nF,0603,10%,100V,X7R' ,1464, NULL;
SELECT Excel2.GBC, Excel2.Description, Excel2.Buildneed, Excel2.Replaced
INTO NewTable
FROM (SELECT GBC, Description, sum(Buildneed) as Buildneed, Replaced FROM Excel GROUP BY GBC, Description, Replaced) as Excel2;
SELECT *
FROM NewTable
See SQL Fiddle for an example: sqlfiddle.com/#!18/d568e/5/2

Related

Create a table with data validation based on 2 or more columns

I have been trying to create a production ERP using C# and SQL Server.
I want to create a table where the insert statement should only occur when at least one of the 3 main columns have a different value.
The main columns are prod_date, order_no, mach_no, shift_no, prod_type. If all the values are repeated a second time the data must not be entered.
create table p1_order(id int not null,
order_no int not null,
prod_date date notnull,
prod_type nvarchar(5),
shift_no int not null,
mach_no nvarchar(5) not null,
prod_qty,
float not null)
Based on the information you provided, You should check for the identical values when executing insert query, while writing your code. for example you can write:
if(prod_date == order_no == mach_no)// or any other 3 variables
{
//error of identical values
}
else{
// your insert query
}
The best way to implement this is by creating a unique constraint on the table.
alter table p1_order
add constraint UC_Order unique (prod_date,order_no,mach_no,shift_no,prod_type);
Due to some reason, if you are not able to create a unique constraint, you can write your query like the following using NOT EXISTS
insert into p1_order (order_no , prod_date , prod_type <remaining columns>)
select 123, '2022-09-20 15:11:43.680', 't1' <remaining values>
where not exists
(select 1
from p1_order
where order_no = 123 AND prod_date = '2022-09-20 15:11:43.680' <additional condition>)

How to make SQL server recognize unique Thai characters?

Here's my table:
id name
1 ទឹក កាបូន
2 លីអូ បៀរ
3 ស្របៀរ ២៤
4 ស្រាបៀរ ឌ្រាប់
When I query using this statement: SELECT * FROM t1 WHERE name = N'លីអូ បៀរ', it returns all rows. This is weird since those Thai characters are different.
Also, this will cause an issue if I make the name column as unique. Does anyone encounter the same issue and what is the possible fix? I tried changing the collation but still no avail.
How to make SQL server recognize unique Thai characters?
Bing translate identifies those characters as Khmer, not Thai. So you need to pick a collation that has language-specific rules for those characters, eg
drop table if exists t1
create table t1(id int, name nvarchar(200) collate Khmer_100_CI_AI )
insert into t1(id,name)
values (1, N'ទឹក កាបូន'),(2, N'លីអូ បៀរ'),(3, N'ស្របៀរ ២៤'),(4, N'ស្រាបៀរ ឌ្រាប់')
SELECT * FROM t1 WHERE name = N'លីអូ បៀរ'
Or use binary collation, that simply compares the characters by their code point values. eg
drop table if exists t1
create table t1(id int, name nvarchar(200) collate Latin1_General_100_BIN2 )
insert into t1(id,name)
values (1, N'ទឹក កាបូន'),(2, N'លីអូ បៀរ'),(3, N'ស្របៀរ ២៤'),(4, N'ស្រាបៀរ ឌ្រាប់')
SELECT * FROM t1 WHERE name = N'លីអូ បៀរ'
Even some of the newer Latin collations will work, eg
drop table if exists t1
create table t1(id int, name nvarchar(200) collate Latin1_General_100_CI_AI )
insert into t1(id,name)
values (1, N'ទឹក កាបូន'),(2, N'លីអូ បៀរ'),(3, N'ស្របៀរ ២៤'),(4, N'ស្រាបៀរ ឌ្រាប់')
SELECT * FROM t1 WHERE name = N'លីអូ បៀរ'

Is it possible to perform a regex pattern match in a SQL Server varchar(max) column and return the match?

I have a log table that has some records that have this type of pattern:
.... "RefundId":"re_1ABasdf234234343434", "..."....
I want to extract and return the value of the RefundId in a column in a select statement, is this possible?
If there is only one Refund_ID for each row then you can use something like this:
--Create table
create table T1 (
T1_id int identity(1,1) primary key clustered,
Log_Data varchar(max) null
)
--Insert test data
insert T1(Log_Data)
values('.... "RefundId":"re_1ABasdf234234343434", "..."....'),
(' "RefundId":"JHHJJHJHJHJJHJH", "..."....'),
(''),
(null)
--Get some results
select *, left(substring(Log_Data, patindex('%"RefundId":"%', Log_Data)+12, 20000000), patindex('%"%', substring(Log_Data, patindex('%"RefundId":"%', Log_Data)+12, 20000000)) + case when patindex('%"%', substring(Log_Data, patindex('%"RefundId":"%', Log_Data)+12, 20000000)) > 0 then -1 else 0 end ) Refund_ID
from T1
If there are multiple Refund_IDs for each value then you will have to find a different method.
You can use the keyword LIKE
SELECT RefundId
FROM MyTable
WHERE RefundId LIKE 'some pattern'

Temp tables, Column name or number of supplied values does not match table definition

Even though this tends to look as a duplicate, I had to post it as I can't seem to spot the error.
I don't know if I am mad or what but I can't seem to spot why there is a mismatch in the number of supplied values.
Here are they:
CREATE TABLE #TIPSTOPE_TS
(
TIP INT NULL,
SIFVAL VARCHAR(5),
GRUPA INT NULL,
DATUMOD VARCHAR(15),
PASIVNA DECIMAL(15,4) NULL DEFAULT(0),
REDOVNA DECIMAL(15,4) NULL DEFAULT(0),
ZATEZNA DECIMAL(15,4) NULL DEFAULT(0),
STOPA DECIMAL(15,4) NULL DEFAULT(0),
DATUMDO VARCHAR(15),
KONTO VARCHAR(15),
)
INSERT INTO #TIPSTOPE_TS
SELECT TS.TIP,
TS.SIFVAL,
TS.GRUPA,
CASE WHEN ISDATE(MAX(TS.DATUMOD)) = 0 THEN '2017.12.31' ELSE MAX(TS.DATUMOD) END AS DATUMOD,
CAST (2 AS DECIMAL(10,4)) AS PASIVNA,
CAST (1 AS DECIMAL(10,4)) AS REDOVNA,
CAST (3 AS DECIMAL(10,4)) AS ZATEZNA,
TS.REDOVNA,
TS.DATUMDO,
TP.M1 AS KONTO
FROM TIPSTOPE TS WITH(NOLOCK)
JOIN TIPPART TP WITH(NOLOCK) ON TP.TIP = TS.TIP
WHERE TS.DATUMOD <= '2017.12.31'
GROUP BY TS.TIP,TS.SIFVAL,TS.GRUPA,TP.M1,TS.DATUMDO,TS.REDOVNA
CREATE NONCLUSTERED INDEX IX_TIPSTOPE_TS ON #TIPSTOPE_TS (TIP, GRUPA, SIFVAL)
INCLUDE (DATUMOD)
And the second one...
CREATE TABLE #UNPVT_TIPSTOPE_TS
(
TIP INT NULL,
SIFVAL VARCHAR(5) NULL,
GRUPA INT NULL,
DATUMOD VARCHAR(10) NULL,
TIP_KS VARCHAR(15) NULL,
KAMATNA_STOPA DECIMAL(15,4) NULL DEFAULT(0),
DATUMDO VARCHAR(10) NULL,
)
INSERT INTO #UNPVT_TIPSOPE_TS
SELECT TIP, SIFVAL, GRUPA, DATUMOD, TIP_KS, KAMATNA_STOPA,DATUMDO
FROM
(
SELECT TIP, SIFVAL, GRUPA, DATUMOD, ISNULL(REDOVNA,0) AS REDOVNA, ISNULL(PASIVNA,0) AS PASIVNA, ISNULL(ZATEZNA,0) AS ZATEZNA,STOPA,DATUMDO
FROM #TIPSTOPE_TS
) P
UNPIVOT (KAMATNA_STOPA FOR TIP_KS IN (REDOVNA, PASIVNA, ZATEZNA)) AS UNPVT
The second temp tables is taking data from the first one.
When I try to create the second one error is thrown:
Insert error: Column name or number of supplied values does not match table definition
You are specifying the exact number of values that are needed. If you copy the whole code in new query window and execute it, it will work. Or in your current window drop the table table:
DROP TABLE #TIPSTOPE_TS;
DROP TABLE #UNPVT_TIPSTOPE_TS;
I mean execute only the above statements, and the execute the rest of the code. It should work again.
Sometime, when are debugging we forgot that the temporary table meta data is cached. For example, you can have the following code:
DROP TABLE IF EXISTS #TEST;
CREATE TABLE #TEST
(
[A] INT
);
INSERT INTO #TEST ([A])
SELECT 1;
And its valid. If we change it to this:
DROP TABLE IF EXISTS #TEST;
CREATE TABLE #TEST
(
[A] INT
,[B] INT
);
INSERT INTO #TEST ([A], [B])
SELECT 1, 2;
We will get:
Msg 207, Level 16, State 1, Line 9 Invalid column name 'B'.
Because, in the current session the #TEST table already exists and the engine is able to check that the B column does not exists. So, we need to drop the table manually, after the columns are changed, or we need to drop the tables at the end of our code statements.

SQL Server : replace UDF with a joined view

I'd would like to ask your help with a gordian knot in my head with regards to SQL Server. I'm trying to replace an UDF with a joined view, but I'm struggling to get the view to return what I need. A bit of clever ordering or so may well do the trick, I'm stuck.
Unfortunately I can't sign up to SQL fiddle at the moment so I have to present the test data here:
CREATE TABLE #Contacts
(
ID INT NOT NULL IDENTITY,
Firstname VARCHAR(50) NULL,
Lastname VARCHAR(50) NULL
)
GO
CREATE TABLE #Cars (ID INT NOT NULL IDENTITY, CarModel VARCHAR(50) NULL)
GO
CREATE TABLE #Ownership
(
Contacts_ID INT NOT NULL,
cars_id INT NOT NULL,
ownership_type TINYINT NOT NULL,
DisplayName VARCHAR(50) NULL
)
GO
CREATE TABLE #Races(ID INT NOT NULL IDENTITY, RaceName VARCHAR(50) NOT NULL)
GO
CREATE TABLE #RaceEntries
(
ID INT NOT NULL IDENTITY,
Races_ID INT NOT NULL,
Contacts_ID INT NOT NULL,
cars_id INT NOT NULL
)
INSERT [#Contacts] ([Firstname], [Lastname])
SELECT
'Justin', 'Case' UNION ALL SELECT
'Gladys', 'Friday' UNION ALL SELECT
'Mandy', 'Lifeboats'
GO
INSERT [#Cars] ([CarModel])
VALUES ('Great Car')
GO
INSERT [#Races] ([RaceName])
VALUES ('A Car Race')
INSERT [#Ownership] ([Contacts_ID], [cars_id], [ownership_type], [DisplayName]) SELECT
1, 1, 0, NULL UNION ALL SELECT
2, 1, 1, NULL UNION ALL SELECT
3, 1, 1, 'Mandy Lifeboats Racing Team'
INSERT [#RaceEntries] ([Races_ID], [Contacts_ID], [cars_id]) SELECT
1, 1, 1 UNION ALL SELECT
1, 3, 1 UNION ALL SELECT
1, 2, 1
What I'd like:
SELECT
[cars_id], mvo.Ownername
FROM
[#RaceEntries] -- join a view that returns the ownername
LEFT OUTER JOIN
#myViewOwnername AS mvo ON mvo.Contacts_ID = [#RaceEntries].[Contacts_ID] AND mvo.Cars_ID = [#RaceEntries].[cars_id]
The issue here is that every car only has one owner (type 0 in ownership). It can have other contacts as representatives.
Usually on lists for #RaceEntries, the owner's name is displayed, unless the representative has an agreed "an override" (so that his or a company name is displayed).
In the above example, for Justin Case's entry it's straight-forward. He is the owner (type 0), end of story.
When Gladys Friday enters (she doesn't have an override "DisplayName") the system should again return Justin Case's name as the owner.
In the last example, Mandy Lifeboats has a DisplayName and therefore that should be returned.
Ideally, I would end up with a view or similar that does the heavy lifting, so that I can join it to x000 records from #RaceEntries (joined on car and contact ID) to get the correct owner name back.
I hope I've simplified the example as much as possible, the real thing is a bit more complex... Please let me know if I should prepare anything else to make helping a bit easier. Many thanks!
I think this might be what you are looking for:
select [#Ownership].Contacts_ID,
[#Ownership].Cars_ID,
coalesce([DisplayName], CarOwners.ContactName) Ownername
into #myViewOwnername
from [#Ownership]
join
(
select [cars_id], Contacts_ID, [#Contacts].Firstname + ' ' + [#Contacts].Lastname ContactName
from [#Ownership]
join [#Contacts]
on [#Ownership].Contacts_ID = [#Contacts].ID
where ownership_type = 0
) CarOwners
on [#Ownership].cars_id = CarOwners.cars_id
A car has one direct owner (type 0), so the sub-query will get you all the owner names of each car. Then you just join that to your ownership table on the cars_id fields. If there is a display name in the ownership table you display that, otherwise you show the car owner's name.

Resources