Creating efficient Multiplication query with individual numbers in SQL Server - sql

I have Table that looks like this :
Code | Column1 | Column2
A01 | 20 | NULL
A02 | 50 | NULL
A03 | 10 | NULL
A04 | 20 | NULL
A05 | 30 | NULL
And I want to update Column2 with the value of Column1 multiplied by some numbers, but only for Code A02,A03 and A04. The multiplicand here doesn't exist in a column and need to be hardcoded.
Example :
A02 = 50x20%
A03 = 10x50%
A04 = 20x100%
Expected Result :
Code | Column1 | Column2
A01 | 20 | NULL
A02 | 50 | 1
A03 | 10 | 5
A04 | 20 | 20
A05 | 30 | NULL
My query right now :
UPDATE A SET
Column1 = Column1*20/100
FROM MyTable A
WHERE Code = 'A02'
UPDATE A SET
Column1 = Column1*50/100
FROM MyTable A
WHERE Code = 'A03'
UPDATE A SET
Column1 = Column1*100/100
FROM MyTable A
WHERE Code = 'A04'
As you can see, it's not very efficient and it's not scalable. Is there any other way to achieve my expected result more efficiently?

Use a JOIN or a CASE expression to handle what value needs to be used instead:
UPDATE dbo.MyTable
SET Column1 = Column1 * CASE Code WHEN 'A02' THEN .2 --As this is a percentage, then use a percentage.
WHEN 'A03' THEN .5 --Percentages are represented as decimals,
WHEN 'A04' THEN 1. --For example, 50% is .5 and 100% is 1.
END
WHERE Code IN ('A02','A03','A04');
GO
UPDATE MT
SET Column1 = MT.Column1 * V.Multiplier
FROM dbo.MyTable MT
JOIN (VALUES('A02',.2),
('A03',.5),
('A04',1.))V(Code,Multiplier) ON MT.Code = V.Code;
For a larger number of values I would suggest that the latter solution is more scalable, and can easily be replaced with something like a table type parameter.

Related

Display two linked values for two id field pointing the same table

In my PostgreSQL database I have a table like this one:
id|link1|link2|
---------------
1 | 34 | 66
2 | 23 | 8
3 | 11 | 99
link1 and link2 fields are both pointing to the same table table2 which has id and descr fields.
I would make an SQL query that returns the same row the id and the descr value for the two field like this:
id|link1|link2|desc_l1|desc_l2|
-------------------------------
1 | 34 |66 | bla | sisusj|
2 | 23 | 8 | ghhj | yui |
3 | 11 | 99 | erd | bnbn |
I've try different queries, but everyone returns two rows per id instead of one.
How can I achieve these results in my PostgreSQL 9.04 database?
Normally, this query should work for you. Assume your first table name's table_name.
SELECT t.id, t.link1, t.link2,
l1.descr AS desc_l1,
l2.descr AS desc_l2
FROM table_name t
LEFT JOIN table2 l1
ON t.link1 = l1.id
LEFT JOIN table2 l2
ON t.link2 = l2.id;
you can use case here Like:
select link1,link2,
case
when link1='34' and link2='66' then 'bla'
when link1='23' and link2='8' then 'ghs'
when link1='11' and link2='99' then 'erd'
end as desc_li,
case
when link1='34' and link2='66' then 'sjm'
when link1='23' and link2='8' then 'yur'
when link1='11' and link2='99' then 'bnn'
end as desc_l2
from table1

Counting points/coordinates that lie within a bounding box

I have 2 tables. The first table contains following columns: Start_latitude, start_longitude, end_latitude, end_longitude, sum. The sum column is empty and needs to be filled based on second table.
The second table contains 3 columns: point_latitude, point_longitude
Table 1
-------------------------
|45 | 50 | 46 | 51 | null|
----|---------------------
|45 | 54 | 46 | 57 | null|
--------------------------
Table2:
---------------
| 45.5 | 55.2 |
---------------
| 45.8 | 50.6 |
---------------
| 45.2 | 56 |
---------------
The null values in table1-row1 would be 1 while in row2 it would be 2. It is the count of number of points that lie within the bounding box.
I can do it in python by writing functions to read values between dataframes. How can this be done in Postgresql. This is a sample problem statement that I came up with for my situation.
Update
This version was tested on PostgreSql 9.3 using SQL Fiddle
UPDATE table1 a
SET sum = sub.point_count
FROM (SELECT a.start_lat, a.end_lat, a.start_lon, a.end_lon, COUNT(*) as point_count
FROM table1 a, table2 b
WHERE b.point_lat BETWEEN start_lat AND a.end_lat
AND b.point_lon BETWEEN a.start_lon AND a.end_lon
GROUP BY a.start_lat, a.end_lat, a.start_lon, a.end_lon) as sub
WHERE a.start_lat = sub.start_lat
AND a.end_lat = sub.end_lat
AND a.start_lon = sub.start_lon
AND a.end_lon = sub.end_lon;
Original answer
Here is my solution, it is tested on MySQL but there is nothing specific about this code so it should work on PostgreSql as well
UPDATE table1 a,
(SELECT a.start_lat, a.end_lat, a.start_lon, a.end_lon, COUNT(*) as count
FROM table1 a, table2 b
WHERE b.point_lat BETWEEN start_lat AND a.end_lat
AND b.point_lon BETWEEN a.start_lon AND a.end_lon
GROUP BY a.start_lat, a.end_lat, a.start_lon, a.end_lon) as sub
SET sum = count
WHERE a.start_lat = sub.start_lat
AND a.end_lat = sub.end_lat
AND a.start_lon = sub.start_lon
AND a.end_lon = sub.end_lon
Note that this query would be much shorter if table1 contained a PK Id column.

Return data having value 0

I'm a newbie so may be a simple SQL query for you guys.
In a table I have records having PFAULT 0 and 1 against one SRID. I want to get only those records which have 0 as PFault. If any record has PFault 1 than I don't need that record.
E.g. a record can have both values i.e. 0 and 1 but I need only those records which don't have 1. field type is bit.
sample table data
ID | SRID | PFault
---- | ---- | ----
2255 | 1212 | 0
2256 | 1212 | 0
2257 | 1212 | 1
2258 | 1213 | 0
2259 | 1213 | 1
2260 | 1214 | 0
2261 | 1214 | 0
2262 | 1216 | 0
as per above I need data for
SRID 1214 and 1216
I assume you are referring to the SRIDs. If that is all you need:
select srid
from t
group by srid
having max(Pfault) = 0;
You can also write this as:
have max(cast(Pfault as int)) = 0
If you want the original rows:
select t.*
from t
where not exists (select 1 from t t2 where t2.srid = t.srid and t2.Pfault = 1);
You almost phrased it in English already in a way that can be translated quite straightforwardly to SQL. That's a very good start. That straightforward translation then looks like:
select srid from table
except
select srid from table where pfault = 1;
SELECT SRID
FROM #Table Otr
WHERE PFault = 0 AND NOT EXISTS(SELECT 1 FROM #Table inr WHERE inr.pfault = 1 AND inr.SRID = Otr.SRID)
GROUP BY SRID

TSQL SSRS Cross Reference another column

ID | Col2 | Col3 | SequenceNum
--------------------------------
1 | x | 12 | 5
2 | y | 11 | 6
3 | a | 45 | 7
100 | b | 23 | 8
101 | a | 16 | 9
102 | b | 28 | 10
4 | a | 9 | 11
5 | b | 26 | 12
6 | x | 100 | 13
I have an SSRS report at the moment which you can enter the ID for and it'll show you data for those ID's. For example lets say you enter start ID 2 end ID 5 it'll report back 2,3,4,5 with Col2 and Col3 data.
But what I really want to happen is for it to return 2,3,100,101,102,3,4,5
I believe may be some way to cross reference the SequenceNum column but I'm fairly new to SQL and SSRS can anyone help?
So an user would enter a parameters...
start-ID = 2 which has a SequenceNum of 6
and end-ID = 5 which has an SequenceNum of 12
Extract your starting and ending sequence numbers from value supplied by starting id and ending id respectively and use them in WHERE condition as below
DECLARE #StartingSeqNum INT, #EndingSeqNum
SELECT #StartingSeqNum = SeqNum FROM tableName WHERE ID = #start_id
SELECT #EndingSeqNum = SeqNum FROM tableName WHERE ID = #end_id
SELECT Col2,Col3
FROM tableName
WHERE SeqNum BETWEEN #StartingSeqNum AND #EndingSeqNum
As you are using SSRS you can specify a Value and a Label for your parameters.
Create a dataset with the following SQL as the source:
select distinct ID as Label
,SequenceNum as Value
from YourTable
order by SequenceNum
And then in the properties for your parameter, in Available Values select Get values from query and then select the above dataset. Set the Value field and Label field as your label and value columns and then click OK. You will need to do this for your start and end parameters, using the same dataset.
Your parameters will now be drop down menus that display the ID value to the user, but passes the SequenceNum value to your query. You can then use these to filter your main dataset.

SQL Insert record on For each record of the result set

Need some advise on the scenario below. I have two joined tables (say table A and Table B)
Table A has the column ContrastId while Table B has HueID, they were joined by ColorId
Select ColorCD, ContrastId, HueId,
From TableA TA
Inner JOIN TableB TB
TA.ColorID = TB.ColorID
The results of the above select statement should be inserted to another table (say Table C)
Example of results:
ColorCD | ContrastID | HueID
-----------------------------
111000 | 123 | 555
111100 | 114 | 548
110015 | 128 | 265
What I want to happened in the Table C, where in I need to put the result set is shown below.
Table C
INSERT INTO dbo.TableC (Gen_N, ColorCD, ColorType ,Identifier, ProcessDT)
SELECT Gen_N, ColorCD, 'Contrast' ,Identifier, ProcessDT
From TableA TA
Inner JOIN TableB TB
TA.ColorID = TB.ColorID
Gen_N | ColorCD | ColorType | Identifier
------------------------------------------
Color | 111000 | Contrast | 123
Color | 111000 | Hue | 555
Color | 111100 | Contrast | 148
Color | 111100 | Hue | 548
Color | 110015 | Contrast | 128
Color | 110015 | Hue | 256
Apologies on the layout, I don't know how to insert a table here. :) Thanks a lot for the help. I believe I need to do a loop here to get every record of the result set just not sure how to.
Any help please? Thanks a lot
You shouldn't need a loop for this. Assuming your fields are correct, you can do this Insert with a Union for each of the types.
This should work for the implied structure:
Insert TableC (Gen_N, ColorCD, ColorType, Identifier, ProcessDT)
Select Gen_N, ColorCD, 'Contrast', ContrastId, ProcessDT
From TableA TA
Join TableB TB On TA.ColorID = TB.ColorID
Union All
Select Gen_N, ColorCD, 'Hue', HueID, ProcessDT
From TableA TA
Join TableB TB On TA.ColorID = TB.ColorID