Creating calculated fields in sql - sql-server

This will seem rudimentary but I can't find a concise example online that matches up.
I have three fields; m1, m2, and m3. I need to create a column or field that is the average of them three. The calculated field would be titled employment. Would the following code be suffice?
ALTER TABLE dbo.tablename ADD Employment AS Select ((m1+m2+m3)/3)
Sample data
m1 20 20 30
m2 15 17 25
m3 60 77 13
desired result.
Name m1 m2 m3 Employment
Auto body 20 20 30 23
Auto Parts 15 17 25 19
Auto Sales 60 77 13 50

You are very close, it's called Computed Column
https://technet.microsoft.com/en-us/library/ms191250(v=sql.105).aspx
ALTER TABLE dbo.tablename ADD Employment AS ((m1+m2+m3)/3)
Update:
If you would like to force data type for a computed column, you could do the following
ALTER TABLE dbo.tablename ADD Employment AS CAST((m1+m2+m3)/3 AS Numeric (9,0))

You can check Computed Columns
CREATE TABLE t1(
col1 int,
col2 int,
col3 int,
col4 as (col1*col2*col3)/3
)
insert into t1 values(1,2,3)
select * from t1

Related

Convert multi-row table into one row based on identifier and column values in SQL?

Here is the Table I am working with (Table1):
Customer ID
Month
Amount Paid
ABC123
1
10
ABC123
2
20
ABC123
3
30
ABC123
4
40
ABC999
1
15
ABC999
2
30
This is what I want my new table to look like (Table2):
Customer ID
AmtPaid_M1
AmtPaid_M2
AmtPaid_M3
AmtPaid_M4
ABC123
10
20
0
40
ABC999
15
30
0
0
I want to just have one row per Customer ID that shows how much they paid each month, instead of having the ID repeated for each month. Is there a simple way to do this using joins or case when statements? Thank you!
You can use pivot
Schema and insert statements:
create table Table1(Customer_ID varchar(50), Month int, Amount_Paid int);
insert into Table1 values('ABC123', 1, 10);
insert into Table1 values('ABC123', 2, 20);
insert into Table1 values('ABC123', 3, 30);
insert into Table1 values('ABC123', 4, 40);
insert into Table1 values('ABC999', 1, 15);
insert into Table1 values('ABC999', 2, 30);
Query:
select Customer_Id, [1] AmtPaid_M1,[2]AmtPaid_M2,[3] AmtPaid_M3, [4] AmtPaid_M4 from Table1
pivot
(
max(Amount_Paid) for Month in ([1],[2],[3],[4])
)pvt
Output:
Customer_Id
AmtPaid_M1
AmtPaid_M2
AmtPaid_M3
AmtPaid_M4
ABC123
10
20
30
40
ABC999
15
30
null
null
** Assuming that you are using SQL Server
db<>fiddle here

SQL Server Insert Into Pivoted View

Let's say I have a table testpivot that looks like this, with district and metric a unique key:
id
district
metric
value
1
a
work
40
2
a
hours
80
3
b
work
50
4
b
hours
85
I create a view:
CREATE VIEW vpivot
AS
SELECT *
FROM(
SELECT district, metric, value
FROM testpivot
)t
PIVOT(SUM(value) for metric IN(work,hours)) as p
So querying from the view looks like this:
district
work
hours
a
40
80
b
50
85
Is there a way to make an insert query like this work:
INSERT INTO vpivot SELECT 'c',20,80
Select * from vpivot
UNION
SELECT 'c',20,80

SQL Return datas from the second table based on the data of the first table

I have two SQL Server tables that are not linked together (No join) and I want to get the data from the second table based on the data of the first table. In the first table I have this:
Table 1
id name
----------
4 BOX-A
8 PART-D
Table 2
id name
------------
14 BOX-A1
25 BOX-A2
38 TOOL-A1
39 TOOL-A2
40 PART-D1
41 PART-D2
What I want to do is that for each name found in table 1, I want to return all the matches in the table 2, so at the end I will have something like this:
id name
-----------
14 BOX-A1
25 BOX-A2
40 PART-D1
41 PART-D2
You can use join or exists:
select t2.*
from table2 t2
where exists (select 1 from table1 t1 where t2.name like concat(t1.name, '%'));

Pivot query without knowing the number of columns needed

I have a query that returns the following data.
ProductCode DealRef
1120 23
1120 76
1130 24
Is there a way that if a product code has more than one Deal ref then it will put this into a new column? So the current result would look something like;
ProductCode Deal1 Deal2
1120 23 76
1130 24
If this is not possible then I have an idea that could work. I would do a count on the DealRef column to find out many columns i would need to pivot to. I would then need to add another column to my initial query which will be able to add an id to each row displaying something similar to the below which I'm unsure how to do.
ProductCode DealRef id
1120 23 1
1120 76 2
1130 24 1
You cannot get the fitting number of columns, but you can get as many columns as you expect to be the maximum, most of them beeing NULL:
Paste this into an empty query window and execute. Adapt to your needs
DECLARE #tbl TABLE(ProductCode INT, DealRef INT);
INSERT INTO #tbl VALUES
(1120,23)
,(1120,76)
,(1130,24);
SELECT p.*
FROM
(
SELECT 'deal' + CAST(ROW_NUMBER() OVER(PARTITION BY tbl.ProductCode ORDER BY tbl.ProductCode) AS VARCHAR(10)) AS ColumnName
,tbl.ProductCode
,tbl.DealRef
FROM #tbl AS tbl
) AS x
PIVOT
(
MIN(DealRef) FOR ColumnName IN(deal1,deal2,deal3,deal4 /*Add as many Col-names as you could maximum need*/)
) AS p
Result is
ProductCode deal1 deal2 deal3 deal4
1120 23 76 NULL NULL
1130 24 NULL NULL NULL

SQL Server 2008: produce table of unique entries

I have the following problem. I have a table with a few hundred thousand records, which has the following identifiers (for simplicity)
MemberID SchemeName BenefitID BenefitAmount
10 ABC 1 10000
10 ABC 1 2000
10 ABC 2 5000
10 A.B.C 3 11000
What I need to do is to convert this into a single record that looks like this:
MemberID SchemeName B1 B2 B3
10 ABC 12000 5000 11000
The problem of course being that I need to differentiate by SchemeName, and for most records this won't be a problem, but for some SchemeName wouldn't be captured properly. Now, I don't particularly care if the converted table uses "ABC" or "A.B.C" as scheme name, as long as it just uses 1 of them.
I'd love hear your suggestions.
Thanks
Karl
(Using SQL Server 2008)
based on the limited info in the original question, give this a try:
DECLARE #YourTable table(MemberID int, SchemeName varchar(10), BenefitID int, BenefitAmount int)
INSERT INTO #YourTable VALUES (10,'ABC' ,1,10000)
INSERT INTO #YourTable VALUES (10,'ABC' ,1,2000)
INSERT INTO #YourTable VALUES (10,'ABC' ,2,5000)
INSERT INTO #YourTable VALUES (10,'A.B.C',3,11000)
INSERT INTO #YourTable VALUES (11,'ABC' ,1,10000)
INSERT INTO #YourTable VALUES (11,'ABC' ,1,2000)
INSERT INTO #YourTable VALUES (11,'ABC' ,2,5000)
INSERT INTO #YourTable VALUES (11,'A.B.C',3,11000)
INSERT INTO #YourTable VALUES (10,'mnp',3,11000)
INSERT INTO #YourTable VALUES (11,'mnp' ,1,10000)
INSERT INTO #YourTable VALUES (11,'mnp' ,1,2000)
INSERT INTO #YourTable VALUES (11,'mnp' ,2,5000)
INSERT INTO #YourTable VALUES (11,'mnp',3,11000)
SELECT
MemberID, REPLACE(SchemeName,'.','') AS SchemeName
,SUM(CASE WHEN BenefitID=1 THEN BenefitAmount ELSE 0 END) AS B1
,SUM(CASE WHEN BenefitID=2 THEN BenefitAmount ELSE 0 END) AS B2
,SUM(CASE WHEN BenefitID=3 THEN BenefitAmount ELSE 0 END) AS B3
FROM #YourTable
GROUP BY MemberID, REPLACE(SchemeName,'.','')
ORDER BY MemberID, REPLACE(SchemeName,'.','')
OUTPUT:
MemberID SchemeName B1 B2 B3
----------- ----------- ----------- ----------- -----------
10 ABC 12000 5000 11000
10 mnp 0 0 11000
11 ABC 12000 5000 11000
11 mnp 12000 5000 11000
(4 row(s) affected)
It looks that PIVOTS can help
The schemename issue is something that will have to be dealt with manually since the names can be so different. This indicates first and foremost a problem with how you are allowing data entry. You should not have these duplicate schemenames.
However since you do, I think the best thing is to create cross reference table that has two columns, something like recordedscheme and controlling scheme. Select distinct scheme name to create a list of possible schemenames and insert into the first column. Go through the list and determine what the schemename you want to use for each one is (most willbe the same as the schemename). Once you have this done, you can join to this table to get the query. This will work for the current dataset, however, you need to fix whatever is causeing the schemename to get duplicated beofre going further. YOu will also want to fix it so when a schemename is added, you table is populated with the new schemename in both columns. Then if it later turns out that a new one is a duplicate, all you have to do is write a quick update to the second column showing which one it really is and boom you are done.
The alternative is to actually update the schemenames that are bad in the data set to the correct one. Depending on how many records you have to update and in how many tables, this might be a performance issue.This too is only good for querying the data right now and doesn't address how to fix the data going forth.

Resources