Unable to fetch modify data in select query [duplicate] - sql

This question already has answers here:
Increased amount of each row in sql
(4 answers)
Closed 8 years ago.
I did not get a good answer for my previous question. In this question I provide more thing but still not get proper result.. anyone help me...
1st row amount=1200,
2nd row amount=1320(1200+120),
3rd row amount=1452(1320+132)
Logic is 10% add with previous amount
;WITH nums AS
(SELECT 1 AS RowNum, 1200 AS value
)
SELECT RowNum, Value
FROM nums
Results:
Sno - Name- Amount
1 - A - 1200
Now I want result like this..
Sno - Name- Amount
1 - A - 1200
2 - A - 1320
3 - A - 1452
Can anybody help me I'm not find any logic for that in same query no external table create or implement

I come from Oracle background; but I hope this helps as it works for me in Oracle:
WITH nums(rn, value) AS
(
SELECT ROWNUM rn, 1200 AS value FROM DUAL
UNION ALL
SELECT rn + 1 rn, round(value * 1.1) FROM nums
where rn < 100
)
SELECT RowNum, Value
FROM nums
It generates up to 100 rows.

You need to use Recursive CTE like this :
WITH nums(rn, value) AS
(
SELECT 1 rn, 1200 AS value
UNION ALL
SELECT rn + 1 rn, value + round(value/10,2) as value
FROM nums
where rn < 10
)
SELECT rn, Value
FROM nums
SQL Fiddle Demo

Related

Snowflake: Repeating rows based on column value

How to repeat rows based on column value in snowflake using sql.
I tried a few methods but not working such as dual and connect by.
I have two columns: Id and Quantity.
For each ID, there are different values of Quantity.
So if you have a count, you can use a generator:
with ten_rows as (
select row_number() over (order by null) as rn
from table(generator(ROWCOUNT=>10))
), data(id, count) as (
select * from values
(1,2),
(2,4)
)
SELECT
d.*
,r.rn
from data as d
join ten_rows as r
on d.count >= r.rn
order by 1,3;
ID
COUNT
RN
1
2
1
1
2
2
2
4
1
2
4
2
2
4
3
2
4
4
Ok let's start by generating some data. We will create 10 rows, with a QTY. The QTY will be randomly chosen as 1 or 2.
Next we want to duplicate the rows with a QTY of 2 and leave the QTY =1 as they are.
Obviously you can change all parameters above to suit your needs - this solution works super fast and in my opinion way better than table generation.
Simply stack SPLIT_TO_TABLE(), REPEAT() with a LATERAL() join and voila.
WITH TEN_ROWS AS (SELECT ROW_NUMBER()OVER(ORDER BY NULL)SOME_ID,UNIFORM(1,2,RANDOM())QTY FROM TABLE(GENERATOR(ROWCOUNT=>10)))
SELECT
TEN_ROWS.*
FROM
TEN_ROWS,LATERAL SPLIT_TO_TABLE(REPEAT('hire me $10/hour',QTY-1),'hire me $10/hour')ALTERNATIVE_APPROACH;

Oracle select similar values [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
i have a database table with a lot of values like this: 340.13 and 232.89.
Now i want to select the value with the best match with a comparison value.
Is this possible without great effort?
This will match values that are within +-10% of the search value and, if there are multiple values, will find the closest match by absolute difference.
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE TABLE_NAME ( VALUE ) AS
SELECT 340.13 FROM DUAL UNION ALL
SELECT 232.89 FROM DUAL UNION ALL
SELECT 224.73 FROM DUAL UNION ALL
SELECT 100.00 FROM DUAL;
Query 1:
WITH search_values ( search_value ) AS (
SELECT 330 FROM DUAL UNION ALL
SELECT 230 FROM DUAL
)
SELECT search_value,
value
FROM (
SELECT search_value,
value,
RANK() OVER ( PARTITION BY Search_value
ORDER BY ABS( value - search_value ) ) AS rnk
FROM table_name t
INNER JOIN
search_values v
ON ( t.value BETWEEN search_value * 0.9 AND search_value * 1.1 )
)
WHERE Rnk = 1
Results:
| SEARCH_VALUE | VALUE |
|--------------|--------|
| 230 | 232.89 |
| 330 | 340.13 |
This is a pretty basic and common task so here is the general approach.
First you need to decide on "best-match-criteria". Basically it as a function of value stored in row and input value. So you can implement this function and evaluate it calling something like MATCH_RATING(COLUMN, :value) for each row. Now that you have this rating for every row, you can sort rows in any way you like and filter the most fitting one (ROWNUM is great for this as are analytic functions like RANK or ROW_NUMBER).
SELECT *
FROM (
SELECT VALUE,
MATCH_RATING(VALUE, :input_value) RATING
FROM YOUR_TABLE
ORDER BY RATING DESC)
WHERE ROWNUM = 1
Then a good idea is to check whether your chosen criteria are implemented in language because if they are, using SQL features will surely be bettter performance-wise.
For example, if distance between two numbers is the only thing that concerns you, SQL will look something like this.
SELECT VALUE
FROM (
SELECT VALUE,
ABS(VALUE - :input_value) DISTANCE
FROM YOUR_TABLE
ORDER BY DISTANCE)
WHERE ROWNUM = 1
If your function assumes 0 value on some interval meaning some rows should never get into your resultset then you should also use WHERE clause filtering useless rows (WHERE MATCH_RATING(COLUMN, :value) > 0).
Back to our distance example: let's accept distance not more than 5% of input value.
SELECT VALUE
FROM (
SELECT VALUE,
ABS(VALUE - :input_value) DISTANCE
FROM YOUR_TABLE
WHERE VALUE BETWEEN 0.95 * :input_value AND 1.05 * :input_value
ORDER BY DISTANCE)
WHERE ROWNUM = 1
By the way, index on YOUR_TABLE.VALUE will surely be helpful for this example.

Convert Query in Mysal to SQL?

I am using Entity Framework i got a error '"The query syntax is not valid. Near term ':', line 1, column 109." from system .data.entity.sqlserver. so please tell me to convert below query in SQL
SELECT Agentid,year(Date_Time) as Year,monthname(Date_Time) as Month,SUM(AmountRecevied) as Amount,#rownum := #rownum + 1 AS Rank FROM collection_master,
(SELECT #rownum := 0) r GROUP BY AgentID,year(Date_Time),monthname(Date_Time) ORDER BY
Amount DESC
Agentid logintime AmountReceived
1 2013/10/01 00:10:10 10000
1 2013/10/01 17:23:10 200
1 2013/10/01 00:30:41 3000
2 2013/10/02 05:10:52 1000
3 2013/10/02 09:10:25 2000
3 2013/10/03 10:10:18 2000
2 2013/10/03 13:10:35 7000
I want a query that should display the output as
Agentid Amount Rank
1 13200 1
2 8000 2
3 4000 3
I had Tried below query not getting expected output please check it once
with temp as (
select row_number() over (order by AmountRecevied) as rownum,AgentID,YEAR(Date_Time) as Years,SUM(AmountRecevied) as amount
from tblcollections group by CustomerID,AgentID,Date_Time ,AmountRecevied
select rownum,AgentID,Years,amount from temp
This should do the job: I cant test it, so pls give it a try.
WITH CTE AS
(
SELECT Agentid,year(Date_Time) as Year, MONTH(Date_Time) as Month,SUM(AmountRecevied) as Amount
FROM collection_master,
GROUP BY AgentID,year(Date_Time),MONTH(Date_Time)
)
SELECT *, ROW_NUMBER() OVER (ORDER BY CTE.Amount DESC) AS RANKING
FROM CTE
Order by RANKING

Select Rows in a uniform order

I have a table customer and 100 rows in it. a status column is set for active/inactive customer in the table.
What i want to do is to select all customers from the table in a specific order
ie
first 7 active customers then 3 inactive customers again 7 active customers and 3 inactive and so on
How can I achieve this in a query.
I am using sql server 2008 . Please Help me....
Something like this should do it, based on the minimal requirements you've listed so far:
;with NumberedRows as (
select
*, --TODO - pick columns
ROW_NUMBER() OVER(PARTITION BY status ORDER BY PKID) - 1 as rn
from
table
), AlteredOrdering as (
select
*, --TODO - pick columns
CASE
WHEN status = 'active' THEN (10 * (rn/7)) + (rn % 7)
WHEN status = 'inactive' THEN (10 * (rn/3)) + 7 + (rn % 3)
END as FinalOrder
from NumberedRows
)
select * from AlteredOrdering ORDER BY FinalOrder
Obviously, altering the table and column names as appropriate. PKID is assumed to be some other column in the table against which the individual rows can be ordered.
The magic numbers in the AlteredOrdering CTE are hopefully obvious - 7 and 3 come from the question, and represent how many of each item should appear in each "group". The 10 is the total size of each "group". So if it was 9 active, 4 inactive, the CASE expression would look like:
WHEN status = 'active' THEN (13 * (rn/9)) + (rn % 9)
WHEN status = 'inactive' THEN (13 * (rn/4)) + 9 + (rn % 4)
As far as I am aware you cannot. It would likely require processing of the data once you had retrieved it from SQL
if you have only 100 rows then perhaps limit x,y combine with union can help
select * from table where status=active limit 0,7
union
select * from table where status=inactive limit 7,3
union
select * from table where status=active limit 10,7
union
select * from table where status=inactive limit 17,3
...

Generating Random Number In Each Row In Oracle Query

I want to select all rows of a table followed by a random number between 1 to 9:
select t.*, (select dbms_random.value(1,9) num from dual) as RandomNumber
from myTable t
But the random number is the same from row to row, only different from each run of the query. How do I make the number different from row to row in the same execution?
Something like?
select t.*, round(dbms_random.value() * 8) + 1 from foo t;
Edit:
David has pointed out this gives uneven distribution for 1 and 9.
As he points out, the following gives a better distribution:
select t.*, floor(dbms_random.value(1, 10)) from foo t;
At first I thought that this would work:
select DBMS_Random.Value(1,9) output
from ...
However, this does not generate an even distribution of output values:
select output,
count(*)
from (
select round(dbms_random.value(1,9)) output
from dual
connect by level <= 1000000)
group by output
order by 1
1 62423
2 125302
3 125038
4 125207
5 124892
6 124235
7 124832
8 125514
9 62557
The reasons are pretty obvious I think.
I'd suggest using something like:
floor(dbms_random.value(1,10))
Hence:
select output,
count(*)
from (
select floor(dbms_random.value(1,10)) output
from dual
connect by level <= 1000000)
group by output
order by 1
1 111038
2 110912
3 111155
4 111125
5 111084
6 111328
7 110873
8 111532
9 110953
you don’t need a select … from dual, just write:
SELECT t.*, dbms_random.value(1,9) RandomNumber
FROM myTable t
If you just use round then the two end numbers (1 and 9) will occur less frequently, to get an even distribution of integers between 1 and 9 then:
SELECT MOD(Round(DBMS_RANDOM.Value(1, 99)), 9) + 1 FROM DUAL