Calculating a field from SQL Query Selecting from multiple tables with Union - sql

I have the following query, which works great. The problem I have is that in both tables (and the aggregate unioned table), there is a field called MTGUID. I need to multiply MTGUID by a number (let's say 1.35, for ease of use) and have it return that number in the MTGUID field. I have tried a dozen ways to do this and can't get anything to play ball. I can create a new column for each calculated price, like (BKRETAIL.MTGUID * 1.35) AS MTG1, but we've got tens of thousands of lines of code that specifically use MTGUID. Any ideas?
I'm using Firebird SQL.
SELECT * FROM (
SELECT BKRETAIL.* FROM BKRETAIL WHERE BKRETAIL.MKEY='SOMEKEY'
UNION SELECT BKWHOLESALE.* FROM BKWHOLESALE WHERE MKEY='SOMEKEY')
ORDER BY
case STATUS
WHEN 'RT' then 1
WHEN 'WH' then 2
WHEN 'OL' then 3
WHEN 'OD' then 4
WHEN NULL then 5
else 6
end;

How about this:
SELECT MTGUID * 1.35 as calculatedMTGUID, SUBSEL.* FROM (
SELECT BKRETAIL.* FROM BKRETAIL WHERE BKRETAIL.MKEY='SOMEKEY'
UNION SELECT BKWHOLESALE.* FROM BKWHOLESALE WHERE MKEY='SOMEKEY') SUBSEL
ORDER BY
case STATUS
WHEN 'RT' then 1
WHEN 'WH' then 2
WHEN 'OL' then 3
WHEN 'OD' then 4
WHEN NULL then 5
else 6
end;

try this
SELECT MTGUID * 1.35 AS MTGUID,<list rest OF COLUMNS here>
FROM (
SELECT BKRETAIL.* FROM BKRETAIL WHERE BKRETAIL.MKEY='SOMEKEY'
UNION SELECT BKWHOLESALE.* FROM BKWHOLESALE WHERE MKEY='SOMEKEY')
ORDER BY
case STATUS
WHEN 'RT' then 1
WHEN 'WH' then 2
WHEN 'OL' then 3
WHEN 'OD' then 4
WHEN NULL then 5
else 6
end;

One option would be to replace the original MTGUID column with computed one, ie
rename the original MTGUID column in table(s);
add new MTGUID column with desired expression using COMPUTED BY (expr);
Advantage of this is that you don't have to alter your SQL statements, disadvantage is that you have to maintain the expression in many places (all the tables which have the column). Of course, the queries which need the original MTGUID value must be updated to use the renamed column, but if the number of such statements is significantly lower it could be worth the trouble.
I think a better solution would be to "hide" all this stuff behind a view but this requires alerting your SQL queries...

Related

How can I convert 2 row into column in tsql?

I have 2 row data which I want to make it to be 2 column,
I tried union syntax but it didn't work.
Here is the data I have:
breed 1 breed2
I tried to convert it with this sql
select a.breed union a.breed
but it didn't work.
Here is what you want from the SQL:
breed1,breed2
SELECT
[breed1],
[breed2]]
FROM
(
SELECT 'breed1' myColumn
union
select 'breed2'
) AS SourceTable
PIVOT
(
AVG(mySecondColumn) FOR
myColumn IN ([breed1], [breed2]])
) AS PivotTable;
You can use a self join. This needs a way to pair rows together (so if you have four rows you get 1 and 2 in one result and 3 and 4 in the other rather than another combination).
I'm going to assume you have sequentially numbered rows in an Id column and an odd numbered row is paired with the one greater even Id:
select odd.Data as 'First', even.Data as 'Second'
from TheData odd
inner join TheData even on odd.Id+1 = even.Id
where odd.Id % 2 = 1;
More generally for more columns use of pivot is more flexible.
How about an aggregation query?
select min(breed) as breed1, max(breed) as breed2
from t;

one column with not equal condition in Ms access

I have 5 words in a column where I need to eliminate two words and show the remaining result
Table name temp
Id approval_trade
1 closed
2 closed by
3 open
4 target
5 running
6 now
I need result as given below using not equal to condition
Id approval_trade
3 open
4 target
5 running
6 now
My query
select *
from temp
where approval_trade <> 'closed' and approval_trade <> 'closed by'
Presumably, you have hidden characters that you cannot see but interfere with the comparison. To start, such a query would normally be written using NOT IN:
select *
from temp
where approval_trade not in ('closed', 'closed by');
This is shorter and less prone to accidental error.
In your case, I would ask if this returns the rows you don't want:
select *
from temp
where approval_trade in ('closed', 'closed by');
If it does, then your query (and the not in) version should work. My guess is that they do not. Next, I would go for like. Does this return only the rows you do not want?
select *
from temp
where approval_trade like 'closed*';
If this returns exactly what you want out, then use not like to get what you want:
where approval_trade not like 'closed*'
If this doesn't work, then the problem gets harder. More understanding of what your data exactly looks like and what the queries return would help.

MS SQL Server: Operate current select values in other selected columns

I want to take a value from a selected column to operate the next column. For example:
SELECT CASE
WHEN ID < 4 THEN ID
ELSE 10
END
AS MY_ID,
MY_ID + 5 AS EXTRA_ID
FROM FOO
That would output for IDs 1,2,3,4,5:
MY_ID EXTRA_ID
1 6
2 7
3 8
10 15
10 15
If I do MY_ID + 5 it will complain about MY_ID not existing (it's an alias, so it makes sense) and ID + 5 will read 1+5, 2+5, 3+5, 4+5, 5+5 instead of 1+5, 2+5, 3+5, 4+10, 5+10 when it goes through the ELSE. Is it even possible to do this? I'm doing it in SSRS - Report builder, and need to operate a result that might be set to a defualt value depending on the CASE clause.
You can repeat the same CASE expression with +5 in the end for the extra_id column
SELECT CASE
WHEN ID < 4 THEN ID
ELSE 10
END
AS MY_ID,
CASE
WHEN ID < 4 THEN ID
ELSE 10
END + 5 AS EXTRA_ID
FROM FOO
An alternative is to create the extra_id column value inside SSRS using an expression
= Fields!my_id.value + 5
you cannot reuse the calculation in the same level. Using my_id in the where clause will fail as well. Either you have to calucate it multiple times, place another select around your statement or use a with statement (CTE).
Simply wrap it with another select:
SELECT t.*,
t.my_id + 5 as extra_id
FROM(Your Query) t
Derived columns are not available in the same layer they're being created. By wrapping them with another select, you make them available (that because the inner query is being processed before the outer) .
You just need a subquery to create MY_ID before doing anything with it. By creating MY_ID in the inner query the outer query can use to define new fields.
SELECT
a.MY_ID,
a.MY_ID + 5 AS EXTRA_ID
from
(SELECT
CASE
WHEN ID < 4 THEN ID
ELSE 10
END
AS MY_ID
FROM FOO) as a

Select subquery inside then of case when statement, sqlite bug?

I'm finding that when I try to select a column in a SQL case statement, it doesn't work unless I wrap it in a numeric function. The max(price) seems to select the value in the column, while just price, or price always returns blank.
I think its a bug.
This doesn't work:
SELECT
auction,
CASE WHEN auction='1'
THEN (select max(bid.amount) from bid where bid.auction_id = auction.id)
ELSE price
END as price_string
FROM product
This works:
SELECT
auction,
CASE WHEN auction='1'
THEN (select max(bid.amount) from bid where bid.auction_id = auction.id)
ELSE max(price)
END as price_string
FROM product
Edit: fixed comma.
This is not a bug.
In the query that doesn't work, the two halves of your CASE statement are incompatible. You have an aggregate function (MAX(bid.amount)) that returns a single value for one part of your CASE statement, and the name of a column, which will return a set, for the other part of your CASE statement. You cannot mix aggregates and sets like this.
The query that works does so because both halves of the CASE statement are returning aggregate values and are therefore compatible.
Take a simple table:
test_table
col1 | col2
1 7
5 14
8 3
3 9
If I query like this:
SELECT col1 FROM test_table
I'll get this result, a set:
col1
1
5
8
3
But if I query like this:
SELECT MAX(col1) FROM test_table
I'll get a single value:
8

sql sum up connection time in call detail records table

lets say Ive got Customers Detail Records table which has columns:
UserAId
UserBId
Duration
Impulses
For eample:
UserAId UserBId Duration Impulses
1 2 30 5
1 2 20 3
2 1 10 2
2 3 5 1
Ok, now I would like to write a query which would aggregate total Duration, Impulses and count of calls betweend users without direction so that the result would look like:
UserAId UserBId TotalDuration TotalImpulses TotalCallsCount
1 2 60 10 3
2 3 5 1 1
Is it possible ? If so then how to do this > thanks for help
Of course, if you execute a query like this:
SELECT
UserAId,
UserBId,
SUM(Duration) AS TotalDuration,
SUM(Impulses) AS TotalImpulses,
COUNT(*) AS TotalCallsCount
FROM CustomerDetail
GROUP BY UserAId, UserBId
... you will not get what you want. That is because this query does not aggregate and combine the rows that have UserAId=1 and UserBId=2 with those that have UserAId=2 and UserBId=1.
To do what you want you need a little trick. What you call UserAId and UserBId in the result set are not actually always what you read on the input table. This query will do what you ask:
SELECT
CASE WHEN UserAId<UserBId THEN UserAId ELSE UserBId END AS User_AId,
CASE WHEN UserAId<UserBId THEN UserBId ELSE UserAId END AS User_BId,
SUM(Duration) AS TotalDuration,
SUM(Impulses) AS TotalImpulses,
COUNT(*) AS TotalCallsCount
FROM CustomerDetail
GROUP BY
CASE WHEN UserAId<UserBId THEN UserAId ELSE UserBId END,
CASE WHEN UserAId<UserBId THEN UserBId ELSE UserAId END
... it works even if UserAId=UserBId (you did not state if those two values can or cannot be the same). You will always get as User_AId the lesser of the 2 Ids, and as User_BId the greater of the 2 Ids... even if that combination does not exist as UserAId, UserBId nowhere in the table (obviously only if it does exist as UserBId, UserAId).
I have tested this on SQLFiddle here.
I am no SQL-Server expert. Some engines do allow the GROUP BY clause to reference calculated columns defined in the SELECT expression list without having to redefine them explicitly. This is non standard SQL, but it does make the SQL much more readable. Not sure if SQL-Server supports some sort of syntax for this.