Oracle Apex get Multiple results from checkboxes - oracle

DB = Oracle 11g
Apex = 4.2.6
In the form I have various items which all work great. However I now have a set of check boxes(:P14_DAYS) one for each day of the week.
What I need to do is get all records between :P14_START_DATE :P14_END_DATE, but only within the days select that's checked.
Below is also a sample of the DATE_SETS table
http://i.stack.imgur.com/YAckN.png
so for example
dates 01-AUG-14 - 5-AUG-14 But only require Sundays AND Mondays date would bring back 2 refs.
BEGIN
UPDATE MD_TS_DETAIL
SET job_for = :P14_JOBFORTEM,
job_type_id = :P14_JOB_TYPE_VALUE,
account_id = :P14_ACC_VAL,
qty = :P14_HRS,
rio = :P14_RIO,
post_code = :P14_POSTCODE
WHERE id IN (SELECT D.id
FROM MD_TS_MAST M
LEFT JOIN MD_TS_DETAIL D
ON M.mast_id = D.md_id
LEFT JOIN DATE_SETS
ON ms_date = dt
WHERE eng_id = :P14_ENG_VAL
AND ms_date BETWEEN :P14_START_DATE AND :P14_END_DATE
AND DATE_SETS.col_day = ANY instr(':'||:P14_DAYS||':',Return)
END;
Any help would be much appreciated .

I found this example: http://docs.oracle.com/cd/B31036_01/doc/appdev.22/b28839/check_box.htm#CHDBGDJH
As I can understand, when you choose some values in your checkbox list, item :P14_DAYS receives value, that contains return values of chosen elements of the LOV with delimiters. Then you need to replace this string in your query
AND DATE_SETS.col_day = ANY instr(':'||:P14_DAYS||':',Return)
with
AND instr(':'||:P14_DAYS||':', ':'||DATE_SETS.col_day||':') > 0
Here function instr searches substring DATE_SETS.col_day in string :P14_DAYS. It returns position of substring if substring was found or 0, if not found. Then you compare result of function with 0, and if result > 0, it means that DATE_SETS.col_day is among selected values.

Related

LINQ Query Variable passed to Another LINQ Query

What is the difference between the query in this post:
Save LINQ Query As Variable To Call Another LINQ Query
var parentLoc = (from a in db.PartsLocations
where a.LocationName == aContainer
select a.ParentLocation);
var locations = (from b in db.PartsLocations
where b.LocationID == parentLoc
select b).ToList();
to the following example from this post.
Dim persVogel = From p In db.People
Where p.LastName = "Vogel"
Select p
Dim persVogelPHVIS = From pp In persVogel
Where pp.Company.Name = "PHVIS"
Select pp
Both of these have declared 2 queries and use the first query variable into second query.
What is the reason to use Single() in the first example but was not used in visualstudiomagazine.com article? Thanks
The two samples are fundamentally different.
First Sample
I think you pasted this one incorrectly...from the referenced question, the query should be:
var parentLoc = (from a in db.PartsLocations
where a.LocationName == aContainer
select a.ParentLocation).Single();
var locations = (from b in db.PartsLocations
where b.LocationID == parentLoc
select b).ToList();
(I am going to assume that LocationID and ParentLocation are typed as int.)
In this sample parentLoc is an int - a single instance of a ParentLocation value, obtained from the PartsLocations table. So what you get is an int.
The second linq statement sources its records also from the PartsLocations table. It uses parentLoc to identify records within that table (e.g. where b.LocationID == parentLoc). What you get at the end is a set of PartsLocations records.
The .Single() call is made because you want to compare the result to LocationID in the second statement, and cannot compare int to IEnumerable<int>.
Second Sample
Dim persVogel = From p In db.People
Where p.LastName = "Vogel"
Select p
Dim persVogelPHVIS = From pp In persVogel
Where pp.Company.Name = "PHVIS"
Select pp
In the second sample, persVogel is a subset of records from the People table (specifically, the subset of people with LastName == "Vogel") - so what you get is a set of People records.
The second linq statement is based on this subset of records (From pp In persVogel) and further filters them down to records where pp.Company.Name = "PHVIS". What you get is still a set of People records.
These two statements could easily be compressed into one single statement:
Dim persVogelPHVIS = From p In db.People
Where p.LastName = "Vogel"
AndAlso p.Company.Name = "PHVIS"
Select p
You will still get a set of People records at the end.

How to make zero counts show in LINQ query when getting daily counts?

I have a database table with a datetime column and I simply want to count how many records per day going back 3 months. I am currently using this query:
var minDate = DateTime.Now.AddMonths(-3);
var stats = from t in TestStats
where t.Date > minDate
group t by EntityFunctions.TruncateTime(t.Date) into g
orderby g.Key
select new
{
date = g.Key,
count = g.Count()
};
That works fine, but the problem is that if there are no records for a day then that day is not in the results at all. For example:
3/21/2008 = 5
3/22/2008 = 2
3/24/2008 = 7
In that short example I want to make 3/23/2008 = 0. In the real query all zeros should show between 3 months ago and today.
Fabricating missing data is not straightforward in SQL. I would recommend getting the data that is in SQL, then joining it to an in-memory list of all relevant dates:
var stats = (from t in TestStats
where t.Date > minDate
group t by EntityFunctions.TruncateTime(t.Date) into g
orderby g.Key
select new
{
date = g.Key,
count = g.Count()
}).ToList(); // hydrate so we only query the DB once
var firstDate = stats.Min(s => s.date);
var lastDate = stats.Max(s => s.date);
var allDates = Enumerable.Range(1,(lastDate - firstDate).Days)
.Select(i => firstDate.AddDays(i-1));
stats = (from d in allDates
join s in stats
on d equals s.date into dates
from ds in dates.DefaultIfEmpty()
select new {
date = d,
count = ds == null ? 0 : ds.count
}).ToList();
You could also get a list of dates not in the data and concatenate them.
I agree with #D Stanley's answer but want to throw an additional consideration into the mix. What are you doing with this data? Is it getting processed by the caller? Is it rendered in a UI? Is it getting transferred over a network?
Consider the size of the data. Why do you need to have the gaps filled in? If it is known to be returning over a network for instance, I'd advise against filling in the gaps. All you're doing is increasing the data size. This has to be serialised, transferred, then deserialised.
If you are going to loop the data to render in a UI, then why do you need the gaps? Why not implement the loop from min date to max date (like D Stanley's join) then place a default when no value is found.
If you ARE transferring over a network and you still NEED a single collection, consider applying D Stanley's resolution on the other side of the wire.
Just things to consider...

LINQ groupby on conditional columns

I am building a report from a table that contains the details of a medical chart audit. The significant columns are:
[ProcedureCode] char(5) = Procedure / service performed
[ModifierCode1] varchar(2) = Indicator of non-standard delivery of procedure
[AuditIssueId] int = what was wrong with the use of the procedure and/or modifier code
There may be 0 or many rows per chart. Two of the AuditIssueIds are for:
Incorrect procedure code
Incorrect modifier code
The report groups results by the AuditIssue with subgroups by provider and then each procedure or modifier code reviewed (with counts of all charts / issues found / percent). Here is the first query that gets the chart count:
var providerCharts =
from ad in db.AuditDetails
join p in providers on ad.ProviderId equals p.ProviderId
where ad.ReviewDate >= startDate && ad.ReviewDate <= endDate
&& (filterSpecialtyId == 0 || p.Specialty.SpecialtyId == filterSpecialtyId)
group ad by new { ad.ProviderId, ad.ProcedureCode } into grpIssue
select new
{
ProviderId = grpIssue.Key.ProviderId,
ProcedureCode = grpIssue.Key.ProcedureCode,
ChartCount = grpIssue.Count()
};
This works great, except for one AuditIssue - "Incorrect Modifier Code". This code shows the count for each procedure in the chart but should instead be grouped by modifier.
I have attempted to insert a condition such as this in my grouping with no luck:
(i.AuditIssueId == AuditIssueIds.IncorrectModifierCode)
? ad.ModifierCode1 : ad.ProcedureCode
Do I need to do two queries and union them, or is there a method to achieve this type of dynamic grouping?
Thanks,
Scott

hadoop cascading how to get top N tuples

New to cascading, trying to find out a way to get top N tuples based on a sort/order. for example, I'd like to know the top 100 first names people are using.
here's what I can do similar in teradata sql:
select top 100 first_name, num_records
from
(select first_name, count(1) as num_records
from table_1
group by first_name) a
order by num_records DESC
Here's similar in hadoop pig
a = load 'table_1' as (first_name:chararray, last_name:chararray);
b = foreach (group a by first_name) generate group as first_name, COUNT(a) as num_records;
c = order b by num_records DESC;
d = limit c 100;
It seems very easy to do in SQL or Pig, but having a hard time try to find a way to do it in cascading. Please advise!
Assuming you just need the Pipe set up on how to do this:
In Cascading 2.1.6,
Pipe firstNamePipe = new GroupBy("topFirstNames", InPipe,
new Fields("first_name"),
);
firstNamePipe = new Every(firstNamePipe, new Fields("first_name"),
new Count("num_records"), Fields.All);
firstNamePipe = new GroupBy(firstNamePipe,
new Fields("first_name"),
new Fields("num_records"),
true); //where true is descending order
firstNamePipe = new Every(firstNamePipe, new Fields("first_name", "num_records")
new First(Fields.Args, 100), Fields.All)
Where InPipe is formed with your incoming tap that holds the tuple data that you are referencing above. Namely, "first_name". "num_records" is created when new Count() is called.
If you have the "num_records" and "first_name" data in separate taps (tables or files) then you can set up two pipes that point to those two Tap sources and join them using CoGroup.
The definitions I used were are from Cascading 2.1.6:
GroupBy(String groupName, Pipe pipe, Fields groupFields, Fields sortFields, boolean reverseOrder)
Count(Fields fieldDeclaration)
First(Fields fieldDeclaration, int firstN)
Method 1
Use a GroupBy and group them base on the columns required and u can make use of secondary sorting that is provided by the cascading ,by default it provies them in ascending order ,if we want them in descing order we can do them by reverseorder()
To get the TOP n tuples or rows
Its quite simple just use a static variable count in FILTER and increment it by 1 for each tuple count value increases by 1 and check weather it is greater than N
return true when count value is greater than N or else return false
this will provide the ouput with first N tuples
method 2
cascading provides an inbuit function unique which returns firstNbuffer
see the below link
http://docs.cascading.org/cascading/2.2/javadoc/cascading/pipe/assembly/Unique.html

Linq assign values from one table into another

I am trying to lookup a value of an column from another table and later use the new looked up values in my where clause. For example, I have the following tables below
ID Name
1 Jan
2 Feb
3 March
Product Customer Start End
A C Feb March
A B Jan March
B C March Jan
In the example above, I need to query for the list of records where Start ID is greater than the End ID. For example, B-C-March-Jan is the record I am looking for.
Should I be using join? Also, if possible a query syntax would be very helpful.
My query:
var vInvalidStartEnd = from p in vRecords
where (from t in vTimePeriods where t.Name == p["Start"] select t.TID).First().Cast<int>() > (from t in vTimePeriods where t.TName == p["End"] select t.ID).First().Cast<int>()
select new
{
Product = p["Product"],
Location = p["Location"],
Start = p["Start"],
End = p["End"]
};
Thanks
Assuming ID defines what name is later than another. Tim's issue in comments is probably because, first, it's unusual to use the name value as your link instead of the ID, and second, ID is a poor indication of which month is greater than another. If I had to use month names the way you are, I would probably have an id, a name, and then an order value in the vTimePeriods table.
from p in vRecords
join start in vTimePeriods on p["Start"] equals start["Name"]
join end in vTimePeriods on p["End"] equals end["Name"]
where (int)end["ID"] < (int)start["ID"]
select new
{
Product = p["Product"],
Location = p["Location"],
Start = p["Start"],
End = p["End"]
};
I don't know the specifics of Linq to Dataset, but it would look something like that.

Resources