SQL less than specific value between two columns - sql

I'm trying to make a statement to compare a specific value of '300' between the following two columns:
m02_bal_amount
m01_bal_amount
How would I state that specific value between the two columns I would like to be less than?
i.e between the two columns listed above how can filter to show a difference of 300.
m02 m01
15 400
0 300
90 1000
SELECT * FROM Database where data_pool = 0 and db_load_dt = '2012-01-10' and m02_bal_amount <= m01_bal_amount for fetch only with ur
Thanks very much

Try BETWEEN
SELECT * FROM Database where data_pool = 0 and db_load_dt = '2012-01-10'
AND amount BETWEEN m02_bal_amount AND m01_bal_amount
I do't know your table schema. Try something like this
Update:
SELECT id, name, amount FROM
(
SELECT id, name, (m02_bal_amount - m01_bal_amount ) AS amount
WHERE
data_pool = 0 and
db_load_dt = '2012-01-10'
)
AS temp
WHERE amount > 300

Related

I need a support for sql query

I have a table with 3 columns lower range,upper range, discount amount
I am passing a number and finding in which range it belongs to and retrieving its discount amount
But i am passing a number that not in this table in this case i need the last range discount amount from table
I need a sql query for the same
0-10 100
11-20 200
21-30 300
if i am passing 5 need to get 100
if i am passing 15 200 as result
but if i am passing 50 i need to get 300 as result
Ie. If the value that is passing not in the range need to get the highest ranges discount amount.
Plzz help. Mee
Try this. You can directly pass/use #value in the script as well.
DECLARE #Value INT
SET #Value = 35
SELECT SUM(DISCOUNT) Discount
FROM
(
SELECT
CASE
WHEN upper_range = (SELECT MAX(upper_range) FROM your_table) AND #Value > upper_range THEN DISCOUNT
WHEN #Value BETWEEN lower_range AND upper_range THEN DISCOUNT
ELSE 0
END
DISCOUNT
FROM your_table
) A
Output for value 35 is-
300
With UNION ALL:
select discount
from tablename
where x between lowerrange and upperrange
union all
select max(discount) from tablename
where not exists (
select 1 from tablename
where x between lowerrange and upperrange
)
If the 1st query does not return a result, then the value will be fetched by the 2nd query.
If the 1st query returns a result, then the 2nd will not return anything.
Applies to any major rdbms.

Table not aggregating properly

I am trying to create a list of percentages from a dataset of transactional data using SAS/SQL to understand how a specific department contributes to overall sales count for a given quarter. For example, if there were 100 sales of Store ID 234980 and 20 of those were in department a in Q4 of 2006, then the list should output:
Store ID 234980 , 20%.
This is the code I am using to achieve this result.
data testdata;
set work.dataset;
format PostingDate yyq.;
run;
PROC SQL;
CREATE TABLE aggregatedata AS
SELECT DISTINCT testdata.ID,
SUM(CASE
WHEN testdata.Store='A' THEN 1 ELSE 0
END)/COUNT(Store) as PERCENT,
PostingDate
FROM work.testdata
group by testdata.ID, testdata.PostingDate;
QUIT;
However, the output I am receiving is more like this:
StoreID DepartmentA Quarter
100 1 2014Q1
100 0 2014Q2
100 1 2014Q2
100 0 2014Q2
100 0 2014Q2
100 0 2014Q2
101 1 2015Q3
101 0 2015Q3
101 0 2015Q4
Why does my code not aggregate to the store level?
If you want to group by QTR then you need to transform your date values into quarter values. Otherwise '01JAN2017'd and '01FEB2017'd would be seen as two distinct values even though they would both display the same using the YYQ. format.
proc sql;
create table aggregatedata as
select id
, intnx('qtr',postingdate,0,'b') as postingdate format=yyq.
, sum(store='A')/count(store) as percent
from work.testdata
group by 1,2
;
quit;
You do not want to set both DISTINCT and GROUP BY
Perhaps try:
select t.testingdate
,t.StoreID
,t.Department
,count(t.*) / count(select t2.*
from testdata t2
where t.testingdate = t2.testingdate
and t.StoreID = t2.StoreID) AS Percentage
from testdata t
group by t.testingdate
,t.StoreID
,t.Department
Alternately you could use a left join, which may be more efficient. The nested select to count all records, regardless of department may be more clear to read.

Calculate percentages of columns in Oracle SQL

I have three columns, all consisting of 1's and 0's. For each of these columns, how can I calculate the percentage of people (one person is one row/ id) who have a 1 in the first column and a 1 in the second or third column in oracle SQL?
For instance:
id marketing_campaign personal_campaign sales
1 1 0 0
2 1 1 0
1 0 1 1
4 0 0 1
So in this case, of all the people who were subjected to a marketing_campaign, 50 percent were subjected to a personal campaign as well, but zero percent is present in sales (no one bought anything).
Ultimately, I want to find out the order in which people get to the sales moment. Do they first go from marketing campaign to a personal campaign and then to sales, or do they buy anyway regardless of these channels.
This is a fictional example, so I realize that in this example there are many other ways to do this, but I hope anyone can help!
The outcome that I'm looking for is something like this:
percentage marketing_campaign/ personal campaign = 50 %
percentage marketing_campaign/sales = 0%
etc (for all the three column combinations)
Use count, sum and case expressions, together with basic arithmetic operators +,/,*
COUNT(*) gives a total count of people in the table
SUM(column) gives a sum of 1 in given column
case expressions make possible to implement more complex conditions
The common pattern is X / COUNT(*) * 100 which is used to calculate a percent of given value ( val / total * 100% )
An example:
SELECT
-- percentage of people that have 1 in marketing_campaign column
SUM( marketing_campaign ) / COUNT(*) * 100 As marketing_campaign_percent,
-- percentage of people that have 1 in sales column
SUM( sales ) / COUNT(*) * 100 As sales_percent,
-- complex condition:
-- percentage of people (one person is one row/ id) who have a 1
-- in the first column and a 1 in the second or third column
COUNT(
CASE WHEN marketing_campaign = 1
AND ( personal_campaign = 1 OR sales = 1 )
THEN 1 END
) / COUNT(*) * 100 As complex_condition_percent
FROM table;
You can get your percentages like this :
SELECT COUNT(*),
ROUND(100*(SUM(personal_campaign) / sum(count(*)) over ()),2) perc_personal_campaign,
ROUND(100*(SUM(sales) / sum(count(*)) over ()),2) perc_sales
FROM (
SELECT ID,
CASE
WHEN SUM(personal_campaign) > 0 THEN 1
ELSE 0
end AS personal_campaign,
CASE
WHEN SUM(sales) > 0 THEN 1
ELSE 0
end AS sales
FROM the_table
WHERE ID IN
(SELECT ID FROM the_table WHERE marketing_campaign = 1)
GROUP BY ID
)
I have a bit overcomplicated things because your data is still unclear to me. The subquery ensures that all duplicates are cleaned up and that you only have for each person a 1 or 0 in marketing_campaign and sales
About your second question :
Ultimately, I want to find out the order in which people get to the
sales moment. Do they first go from marketing campaign to a personal
campaign and then to sales, or do they buy anyway regardless of these
channels.
This is impossible to do in this state because you don't have in your table, either :
a unique row identifier that would keep the order in which the rows were inserted
a timestamp column that would tell when the rows were inserted.
Without this, the order of rows returned from your table will be unpredictable, or if you prefer, pure random.

SSRS/T-SQL sum if another condition is met

Basically I have an application that processes transactions. Each transaction has a transaction number. In the application view on the front the total for each transaction is calculated but it is not stored in the database (and this cannot be changed)
Now in SSRS they want to see the value come through on the report. The way to do this is to match the transaction number and if they match (no matter how many records) it adds them up on is there a way to do this on SSRS? Or maybe a more elegant way to do it would be to do it in the stored procedure.
And example of this is below which I know won't work but just to give you an idea of what I'm trying to accomplish here:
SELECT transactionID
, value
, Sum(Case When transactionID = TransactionID Then Value Else 0) As Total
EDIT: In response to some of the comments I made this edit. First off in the above I made a mistake and did TransactionID = transaction but it should be what it is currently.
Continuing on... In order to do this I need to match the transaction number against other transaction numbers in the data set and see if there is a match. To illustrate I did this example below:
This is an example dataset:
TransId: 1 Value: 200
TransId: 2 Value: 300
TransId: 1 Value: 100
TransId: 2 Value: 500
TransId: 1 Value: 400
From this dataset I should get these values in the report:
TransId: 1 Value: 200 Total: 700
TransId: 2 Value: 300 Total: 800
TransId: 1 Value: 100 Total: 700
TransId: 2 Value: 500 Total: 800
TransId: 1 Value: 400 Total: 700
So for each row I want to see the complete total for each record(TransID) and not a runnign total.
Window functions are just so much more fun though:
SELECT TransactionId
, Value
, SUM(Value) OVER(PARTITION BY TransactionId) AS Total
FROM SomeTable
SQL Fiddle
This should do the trick
select transactionID
, value
, TransactionSum
from MyTable t
join (select transactionID
, sum (value) as TransactionSum
from MyTable
group by transactionID
) x on t.transactionID = x.transactionID
Just another way of doing it
select a.transid,
a.value,
(select sum(b.value) from yourTable b where b.transid = a.transid) as Total
from yourTable a

DB2 SQL filter query result by evaluating an ID which has two types of entries

After many attempts I have failed at this and hoping someone can help. The query returns every entry a user makes when items are made in the factory against and order number. For example
Order Number Entry type Quantity
3000 1 1000
3000 1 500
3000 2 300
3000 2 100
4000 2 1000
5000 1 1000
What I want to the query do is to return filter the results like this
If the order number has an entry type 1 and 2 return the row which is type 1 only
otherwise just return row whatever the type is for that order number.
So the above would end up:
Order Number Entry type Quantity
3000 1 1000
3000 1 500
4000 2 1000
5000 1 1000
Currently my query (DB2, in very basic terms looks like this ) and was correct until a change request came through!
Select * from bookings where type=1 or type=2
thanks!
select * from bookings
left outer join (
select order_number,
max(case when type=1 then 1 else 0 end) +
max(case when type=2 then 1 else 0 end) as type_1_and_2
from bookings
group by order_number
) has_1_and_2 on
type_1_and_2 = 2
has_1_and_2.order_number = bookings.order_number
where
bookings.type = 1 or
has_1_and_2.order_number is null
Find all the orders that have both type 1 and type 2, and then join it.
If the row matched the join, only return it if it is type 1
If the row did not match the join (has_type_2.order_number is null) return it no matter what the type is.
A "common table expression" [CTE] can often simplify your logic. You can think of it as a way to break a complex problem into conceptual steps. In the example below, you can think of g as the name of the result set of the CTE, which will then be joined to
WITH g as
( SELECT order_number, min(type) as low_type
FROM bookings
GROUP BY order_number
)
SELECT b.*
FROM g
JOIN bookings b ON g.order_number = b.order_number
AND g.low_type = b.type
The JOIN ON conditions will work so that if both types are present then low_type will be 1, and only that type of record will be chosen. If there is only one type it will be identical to low_type.
This should work fine as long as 1 and 2 are the only types allowed in the bookings table. If not then you can simply add a WHERE clause in the CTE and in the outer SELECT.