Oracle SQL Developer: Sum rows based on value from another column - oracle

Trans. ID QTY TOOL Date
1 20 A2 2015
2 20 A2 2016
3 20 A2 2016
4 20 A3 2015
5 20 A3 2016
6 20 A3 2016
7 20 C 2016
8 20 C 2016
9 20 C 2016
10 20 C 2016
To Return
--Interested in 2016 only
Tool Total
A2 40
A3 40
Im not interested in the individual IDS. Just more interested totals.
Please notw Im also interested in grabbing data with tools specifically starting with the letter A since the actual table has a bunch of tools.
Im having a hard time figuring out how to put the WHERE statement and other things. I read in another thread to use distincts as well.
select Tool, sum(QTY)
from
(select distinct Tool, ID, QTY from "table")
where Tool like 'A%'
AND Date like '2016%'
group by PROCESS_EQP_ID

If you do the distinct in your subquery, you are going to knock out one of the rows with ids 2 and 3. However, from your expected output, you want both to be summed.
Also, what datatype is the date column? If it's DATE or TIMESTAMP, then I think this is what you're after:
select tool, sum(qty)
from "table"
where tool like 'A%'
and to_char(dt, 'yyyy') = '2016' -- note that I've renamed the date column as `date` is a reserved word in Oracle.
group by tool;

Related

Oracle, filter by bits flags

I want to store a structure (Activity) with a Months field, the user can select 1 or more months for each activity, but I have to filter in a query by a specific month.
I have 4 approaches to store de data:
I can create a table Activity_month that each row represents the activity with each month selected.
Store in a Varchar2(12), and each month es a unique character.
Store in a NUMBER(2), and each bit is a month, and the selected month is represented with 1, so the bit array 000100000011 represents that April, November, and December were selected.
Create 12 Number(1) columns for each month.
Which one is better for store and search?
It depends on how you will use it this data... Will you use it to filter data? How often? What filters will be most popular? So you need to answer a few questions:
Will you filter data just by one month? ie show me rows for April
Will you filter it as: give me those rows for April and June, but not January and December?
Will you aggregate rows by month?
Store in a NUMBER(2), and each bit is a month, and the selected month is represented with 1, so the bit array 000100000011 represents that April, November, and December were selected.
Create 12 Number(1) columns for each month.
You can use also virtual columns: for example, you can create 12 Number(1) columns and add virtual column
generated as (jan*power(2,11)+feb*power(2,10)+...+dec*power(2,0)).
But, since Number(1) takes 2 bytes, I'd prefer varchar2(1 byte) with check(... in ('Y','N') (or '0','1'):
SQL> select dump(cast(1 as number(1))) dmp_number_1 from dual;
DMP_NUMBER_1
--------------------
Typ=2 Len=2: 193,2
SQL> select dump(cast('Y' as varchar2(1))) dmp_varchar_1 from dual;
DMP_VARCHAR_1
--------------------
Typ=1 Len=1: 89
In this case you can create virtual column generated as (jan||feb||...||dec).
Or even winter as (jan||feb||dec)
Then you will need to decide if you want to create indexes on them.

Cross lookup in oracle without creating a table

I have a list of 20 records mapping year to a number from 2001 to 2021. For a couple of reasons these can not be loaded into a table, and I do not have permissions to create temporary tables. This lookup means I can't just run a single query in oracle - I have to export and join with a script. Is there a way I could just do a lookup in memory? I could do a CASE WHEN statement to handle each of the 20 cases. But is there some other smoother way to check values against a list in Oracle when you can't write to a table in between?
If I understood you correctly, a CTE might help:
SQL> with years as
2 (select 2000 + level as year
3 from dual
4 connect by level <= 21
5 )
6 select year
7 from years
8 /
YEAR
----------
2001
2002
2003
2004
<snip>
2020
2021
21 rows selected.
SQL>
You'd now join years with other tables, e.g.
with years as
...
select y.year, e.hiredate
from years y join employees e on e.year = y.year
where ...

Checksum in Oracle PL/SQL

Do we have similar kind of checksum function (SQL) in oracle function. I would to store it in a table and use key/value for update statements. One of my current process contains 15 columns, need to check any change is there between source and destination, instead of checking one by one column whether change is happened or not, would like to have single column in table to helps whether change happened in 15 columns
Databases are good at keeping track of changes, that's what they are for.
Maybe the built-in ORA_ROWSCN is good enough for your change tracking? By default it tracks only the changes per block, but you can enable a table to track the change for each row with the - oddly named - clause ROWDEPENDENCIES:
CREATE TABLE t (
a NUMBER,
b NUMBER,
c NUMBER
) ROWDEPENDENCIES;
INSERT INTO t VALUES (1,1,1);
INSERT INTO t VALUES (2,2,2);
SELECT current_scn FROM v$database;
2380496
After a while:
UPDATE t SET b=20, c=20 WHERE a=2;
SELECT current_scn FROM v$database;
2380665
Now you can query the system change number SCN each row was changed:
SELECT ORA_ROWSCN AS scn, a,b,c FROM t;
SCN A B C
2380496 1 1 1
2380665 2 20 20
For the last 5 days, Oracle can translate a SCN to approximate real time (in Oracle 10 ± 5 minutes, from Oracle 11 ± 3 seconds):
SELECT ORA_ROWSCN AS SCN, SCN_TO_TIMESTAMP(ORA_ROWSCN) AS ts, a,b,c FROM t;
SCN TS A B C
2380496 2020-05-15 20:20:38 1 1 1
2380665 2020-05-15 20:23:06 2 20 20
It's documented in Oracles SQL Language Reference.

SSRS, Limit Fixed number of Columns in Matrix within a Tablix - issue in sorting matrix data

I am converting a crystal report to ssrs report, i am trying to implement "Format With Multiple Columns" feature of crystal report to ssrs.
I have a Main tablix that has two Two Groups
1st Group - PolicyType
2nd Group - WeekNumber
Under Week Number group, i have inserted a rectangle and a matrix within it. The matrix will show the policy number generated in every week. The matrix should only contain 6 columns and the grouping for matrix is as below
Row Grouping : Ceiling(RowNumber("WeekNumber") / 6)
Column Grouping : Ceiling(RowNumber("WeekNumber") MOD 6)
I need a output like below
InsuranceType1
Week 1
Policy Number
1001 1002 1003 1004 1005 1006
1007 1008 1009 1010
Week 2
Policy Number
2001 2002 2003 2004 2005 2006
2007 2008 2009 2010
I am able to get a similar output but the sorting within the matrix is not working, ie., i get the following result
InsuranceType1
Week 1
Policy Number
1002 1003 1001 1004 1007 1006
1005 1008 1009 1010
Week 2
Policy Number
2008 2009 2003 2004 2005 2006
2007 2001 2002 2010
i have not used any sorting on the Matrix, nor in the group of matrix the only sorting is on the main tablix groups PolicyType and WeekNumber and both are in ascending order.
What i have tried is:
Sort Matrix using PolicyNumber, but that will only output first row and first column (very strange!!!).
Add an additional sort of PolicyNumber in Group WeekNumber (did not work either)
i have no option of modifying the stored procedure to return the row number back to the report as the client is strict on SP modification as they want to get this report backward compatible.
Please help!!
I have managed to resolve this issue, thought i'll be helpful for others. The order needs to be on the main tablix and not on the inner group or Matrix.

SQL Query with date that does not exist

I was recently working on some SQL queries where I had to separate the values into various months (e.g. December, January, Feb...) and make some comparisons. However I was at a loss for wondering about what to use for the ending day of each month. So I was wondering what happens when you define a date that does not technically exist. For example.
WHERE myDate BETWEEN '2016-01-01' AND '2016-02-31' //note Feb 31 does not exist.
My assumption (based on my current query seeming to return the proper results) is that it simply ignores the extra dates that do not exist (e.g. when counting the dates, it simply has no dates for the range outside of the regular dates).
Is this undefined behavior that I may run into trouble with in the future? Or is there a better way to do this to cover all basis?
Why don't you want to use LAST_DAY() function:
SELECT SYSDATE, trunc(LAST_DAY(SYSDATE)) last,
LAST_DAY(SYSDATE) - SYSDATE days_left FROM DUAL;
Output:
SYSDATE LAST DAYS_LEFT
----------------- ----------------- ----------
03.02.16 18:38:26 29.02.16 00:00:00 26
1 row selected.

Resources