while select with join firstOnly - axapta

Is there any chance i could join two tables like this ?
while select SalesId from salesTable
//group by SalesId
where salesTable.SalesId == "xxx006932683"
join firstOnly SalesPrice, ItemId, LineNum from salesLine
//group by SalesId
order by salesLine.LineDisc asc, salesLine.SalesPrice desc
where salesLine.SalesId == salesTable.SalesId
{
info(strFmt("Sales id : %1 line %2 item %3 price %4", salesLine.SalesId, salesLine.LineNum, salesLine.ItemId, salesLine.SalesPrice));
}
So, for each line in SalesTable, join it with the only one line in SalesLine with the same SalesId and satisfying the order condition.
To be honest, i have tried a lot of groupings and orderings and maxOfs, minOfs with no success... so here i am asking for an idea.

You can not do that in one select statement.
First you can create a view on sales line with grouping on SalesId and maxOf, minOf, ... on fields you need.
This view should return only one record for each SalesId. Than you can join this view to sales table.
If you only want to get first line of order then you have to do nested selects.
Best way is to create a temp table with fields you need and fill it with data.
while select SalesId from salesTable
{
select firstOnly SalesPrice, ItemId, LineNum from salesLine
order by salesLine.LineDisc asc, salesLine.SalesPrice desc
where salesLine.SalesId == salesTable.SalesId
;
//insert into temp table
info(strFmt("Sales id : %1 line %2 item %3 price %4", salesLine.SalesId, salesLine.LineNum, salesLine.ItemId, salesLine.SalesPrice));
}
But in your case (because you have where statement on SalesId <- unique) this will work fine
select firstOnly SalesPrice, ItemId, LineNum from salesLine
order by salesLine.LineDisc asc, salesLine.SalesPrice desc
where salesLine.SalesId == "xxx006932683";

I have to admit this is the most strangest query I have written so far :
SalesQuotationTable salesQuotationTable;
SalesQuotationLine salesQuotationLine;
CustQuotationSalesLink custQuotationSalesLink;
CustQuotationJour custQuotationJour;
;
while select maxof(QuotationId), maxof(CurrencyCode) from salesQuotationTable
group by QuotationId, CurrencyCode, RecId
where salesQuotationTable.QuotationStatus == SalesQuotationStatus::Sent
&& salesQuotationTable.QuotationType == QuotationType::Sales
//&& salesQuotationTable.QuotationId == '00015683_042' just for testing
join maxof(lineNum), minof(lineAmount), maxof(QuotationId) from salesQuotationLine
group by lineNum, lineAmount, QuotationId, RecId
where salesQuotationLine.QuotationId == salesQuotationTable.QuotationId
&& salesQuotationLine.QuotationStatus == SalesQuotationStatus::Sent
&& salesQuotationLine.QuotationType == QuotationType::Sales
&& salesQuotationLine.SalesQty > 0
//duplicate values were coming from here, grouping was the way to go
join maxof(QuotationDate), maxof(QuotationId) from custQuotationSalesLink
group by OrigQuotationId
where custQuotationSalesLink.OrigQuotationId == salesQuotationTable.QuotationId
join maxof(QuotationDate) from custQuotationJour
order by custQuotationJour.QuotationId
where custQuotationJour.QuotationId == custQuotationSalesLink.QuotationId
&& custQuotationJour.QuotationDate == custQuotationSalesLink.QuotationDate
A few notes:
1. Instead of
select firstonly custQuotationSalesLink
order by QuotationDate desc, QuotationId desc
where custQuotationSalesLink.OrigQuotationId == this.QuotationId
I have used
join maxof(QuotationDate), maxof(QuotationId) from custQuotationSalesLink
group by OrigQuotationId
where custQuotationSalesLink.OrigQuotationId == salesQuotationTable.QuotationId
The party starts here, from what i have seen, once using a group by, all the fields from the other tables seem to be empty. So the solution is to add group by everywhere.
You see i am adding the RecId into groupings to be sure i am not really grouping anything :)
In order to get fields with values you have to add an aggregate function in the select clause. Ok , cool, why not, as long as i am not grouping for real.
2. But the catch for me was at the last part:
join maxof(QuotationDate) from custQuotationJour
order by custQuotationJour.QuotationId
where custQuotationJour.QuotationId == custQuotationSalesLink.QuotationId
&& custQuotationJour.QuotationDate == custQuotationSalesLink.QuotationDate
That order by did the trick. I don t know why. If i switch it with a group by which seems normal to me, i get duplicated values. So all the groupings added before are just losing their relevance. I guess sometimes a bit of luck has to join the game too. I mean, why thinking at order by there. Maybe because it s Wednesday, i don t know.
I had to use some aggregation on the last join because otherwise i wouldn t have got a value for the QuotationDate field which in fact is the whole goal of this work.
This link helped me a lot :
http://axatluegisdorf.blogspot.ca/2010/07/select-group-by-and-join-order-by.html

Related

How to build a select query to specify the record which is already existed in other table

I want to specify that a phone number is already existed in other table or not. If it is existed then it must show me 'yes' otherwise show me 'no'. For exanple:
Select Name, PHONE_NO, (Select 'yes' from cdr_personal_info c , tec_personal_info t where c.phone_no=t.phone_no) CDR_existence from TEC_PERSONAL_INFO;
The above query display 'yes' with all columns of TEC_PERSONAL_INFO table it should only display 'yes' with one column which is existed in CDR_PERSONAL_INFO table.
Note: these two tables does not have any kinds of relationship with each other.
You could use an exists condition around your subquery - though you don't need to refer to the driving table again - within a case expression:
select t.name,
t.phone_no,
case when exists (
select null from cdr_personal_info c where c.phone_no=t.phone_no
) then 'yes' else 'no' end as cdr_existence
from tec_personal_info t
Or you could use an outer join, but you might have to deal with duplicates if the cdrpersonal_info table can have the same phone number more than once:
select t.name,
t.phone_no,
case when c.phone_no is null then 'no' else 'yes' end as cdr_existence
from tec_personal_info t
left join cdr_personal_info c on c.phone_no=t.phone_no
db<>fiddle demo with some made-up data.

Replacing EXISTS JOIN with JOIN

I am having trouble with the AX2012 class (default AX2012 class and code, no modifications have been made on it): CustVendTransDetails in the method calcCashDiscounts
The following query is giving me the error The select list for the INSERT statement contains fewer items than the insert list. The number of SELECT values must match the number of INSERT columns.:
if (TaxParameters::canApplyCashDiscOnInvoice_ES())
{
insert_recordset tmpValue
(CustVendTransRefRecId, AmountMST)
select CustVendTransRefRecId
from _custVendAccountStatementIntTmpProcessing
exists join custVendTransLoc
where
custVendTransLoc.RecId == _custVendAccountStatementIntTmpProcessing.CustVendTransRefRecId
exists join firstOnly subledgerVoucherGeneralJournalEntry
where
subledgerVoucherGeneralJournalEntry.Voucher == custVendTransLoc.Voucher &&
subledgerVoucherGeneralJournalEntry.AccountingDate == custVendTransLoc.TransDate
exists join generalJournalEntry
where
generalJournalEntry.RecId == subledgerVoucherGeneralJournalEntry.GeneralJournalEntry &&
generalJournalEntry.Ledger == Ledger::current()
join AccountingCurrencyAmount from generalJournalAccountEntry
where
generalJournalAccountEntry.GeneralJournalEntry == generalJournalEntry.RecId &&
(generalJournalAccountEntry.PostingType == LedgerPostingType::CustCashDisc ||
generalJournalAccountEntry.PostingType == LedgerPostingType::VendCashDisc);
update_recordSet _custVendAccountStatementIntTmpProcessing setting
UtilizedCashDisc = tmpValue.AmountMST,
PossibleCashDisc = tmpValue.AmountMST
join tmpValue
where
tmpValue.CustVendTransRefRecId == _custVendAccountStatementIntTmpProcessing.CustVendTransRefRecId;
}
I understand why, but I am not sure how to solve this problem. Will it be a problem to replace the exist join with a normal join?
Replacing the exist join with join, does solve my problem, but I am not sure what difference it will make to the data? Because it is only is selecting 1 field?
You can try to switch the order of joins:
insert_recordset tmpValue (CustVendTransRefRecId, AmountMST)
select CustVendTransRefRecId
from _custVendAccountStatementIntTmpProcessing
join AccountingCurrencyAmount from generalJournalAccountEntry // Moved up
where generalJournalAccountEntry.PostingType == LedgerPostingType::CustCashDisc ||
generalJournalAccountEntry.PostingType == LedgerPostingType::VendCashDisc
exists join custVendTransLoc
where
custVendTransLoc.RecId == _custVendAccountStatementIntTmpProcessing.CustVendTransRefRecId
exists join firstOnly subledgerVoucherGeneralJournalEntry
where
subledgerVoucherGeneralJournalEntry.Voucher == custVendTransLoc.Voucher &&
subledgerVoucherGeneralJournalEntry.AccountingDate == custVendTransLoc.TransDate
exists join generalJournalEntry
where
generalJournalEntry.RecId == subledgerVoucherGeneralJournalEntry.GeneralJournalEntry && &&
generalJournalEntry.RecId == generalJournalAccountEntry.GeneralJournalEntry && // Moved from join
generalJournalEntry.Ledger == Ledger::current();
Replacing the exist join with join will not fix your issue. Exist is a way to join to essentially inner join to a table without returning any fields.
The query should return CustVendTransRefRecId from _custVendAccountStatementIntTmpProcessing and AccountingCurrencyAmount from generalJournalAccountEntry which is exactly what the insert is expecting.
I expect the query isn't actually returning anything. Check the criteria it is using and check the data.

Insert into Table with the first column being a Sequence

I am trying to use an Insert, Sequence and Select * to work together.
INSERT INTO BRK_INDV
Select * from (Select brk_seq.NEXTVAL as INDV_SEQ, a.*
FROM (select to_date(to_char(REQUEST_DATETIME,'DD-MM-YYYY'),'DD-MM-YYYY') BUSINESS_DAY, to_char(REQUEST_DATETIME,'hh24') src_hour,
CASE tran_type
WHEN 'V' THEN 'Visa'
WHEN 'M' THEN 'MasterCard'
ELSE tran_type
end text,
tran_type, count(*) as count
from DLY_STATS
where 1=1
AND to_date(to_char(REQUEST_DATETIME,'DD-MM-YYYY'),'DD-MM-YYYY') = '09-FEB-2015'
group by to_date(to_char(REQUEST_DATETIME,'DD-MM-YYYY'),'DD-MM-YYYY'),to_char(REQUEST_DATETIME,'hh24'),tran_type order by src_hour)a);
This gives me the following error:
ERROR at line 2:
ORA-02287: sequence number not allowed here
I tried to remove the order by and still the same error.
However, if I only run
Select brk_seq.NEXTVAL as INDV_SEQ, a.*
FROM (select to_date(to_char(REQUEST_DATETIME,'DD-MM-YYYY'),'DD-MM-YYYY') BUSINESS_DAY, to_char(REQUEST_DATETIME,'hh24') src_hour,
CASE tran_type
WHEN 'V' THEN 'Visa'
WHEN 'M' THEN 'MasterCard'
ELSE tran_type
end text,
tran_type, count(*) as count
from DLY_STATS
where 1=1
AND to_date(to_char(REQUEST_DATETIME,'DD-MM-YYYY'),'DD-MM-YYYY') = '09-FEB-2015'
group by to_date(to_char(REQUEST_DATETIME,'DD-MM-YYYY'),'DD-MM-YYYY'),to_char(REQUEST_DATETIME,'hh24'),tran_type order by src_hour)a;
It shows me proper entries. Then, why is select * not working for that?
Kindly help.
I see what you're trying to do. You want to insert rows into the BRK_INDV table in a particular order. The sequence number, which I assume will be the primary key of BRK_INDV, will be generated sequentially in the sorted order of the input rows.
You are working with a relational database. One of the first characteristics we all learn about a relational database is that the order of the rows in a table is insignificant. That's just a fancy word for fugitaboutit.
You cannot assume that a select * from table will return the rows in the same order they were written. It might. It might for quite a long time. Then something -- the number of rows, the grouping of some column values, the phase of the moon -- something will change and you will get them out in a seemingly totally random order.
If you want order, it must be imposed in the query, not the insert.
Here's the statement you should be executing:
INSERT INTO BRK_INDV
With
Grouped( Business_Day, Src_Hour, Text, Tran_Type, Count )As(
Select Trunc( Request_Datetime ) Business_Day,
To_Char( Request_Datetime, 'hh24') Src_Hour,
Case Tran_Type
When 'V' Then 'Visa'
When 'M' Then 'MasterCard'
Else Tran_Type
end Text,
Tran_Type, count(*) as count
from DLY_STATS
Where 1=1 --> Generated as dynamic SQL?
And Request_Datetime >= Date '2015-02-09'
And Request_Datetime < Date '2015-02-10'
Group By Trunc( Request_Datetime ), To_Char( Request_Datetime, 'hh24'), Tran_Type
)
Select brk_seq.Nextval Indv_Seq, G.*
from Grouped G;
Notice there is no order by. If you want to see the generated rows in a particular order:
select * from Brk_Indv order by src_hour;
Since there could be hundreds or thousands of transactions in any particular hour, you probably order by something other than hour anyway.
In Oracle, the trunc function is the best way to get a date with the time portion stripped away. However, you don't want to use it in the where clause (or, aamof, any other function such as to_date or to_char)as that would make the clause non-sargable and result in a complete table scan.
The problem is that you can't use a sequence in a subquery. For example, this gives the same ORA-02287 error you are getting:
create table T (x number);
create sequence s;
insert into T (select * from (select s.nextval from dual));
What you can do, though, is create a function that returns nextval from the sequence, and use that in a subquery:
create function f return number as
begin
return s.nextval;
end;
/
insert into T (select * from (select f() from dual));

LINQ - EF join difficulty

I have two tables:
Phase :
long ID
string Name
and another Activity :
long ID
string Name
long PhaseID
I already know the name of the phases and I want to get the activity for those particular phases. Do i add PhaseName to the activity table or do I do it through join in LINQ?
Maybe something like this?
var query = from a in entities.Activities
join p in entities.Phases on a.PhaseId equals p.Id
where p.Name == "Preplanning"
... and here im not sure how to finish this query..
Thanks for your help!
The code that you've provided will use an Inner Join to find all Activities where the Phase with Name "Preplanning" exists.
To finish your query you need to add a select clause.
var query = from a in entities.Activities
join p in entities.Phases on a.PhaseId equals p.Id
where p.Name == "Preplanning"
select a.Name
will return IEnumerable<string> of all activity names.
Just select activity, as you want:
var query = from a in entities.Activities
join p in entities.Phases on a.PhaseId equals p.Id
where p.Name == "Preplanning"
select a;
Here is how query expression should look like:
A query expression must begin with a from clause and must end with a select or group clause. Between the first from clause and the last select or group clause, it can contain one or more of these optional clauses: where, orderby, join, let and even additional from clauses. You can also use the into keyword to enable the result of a join or group clause to serve as the source for additional query clauses in the same query expression.
Same as puzzling image:
With method syntax you don't need to end query with something special:
var query = entities.Phases
.Where(p => p.Name == "Preplanning")
.Join(entities.Activities, p => p.Id, a => a.PhaseId, (p,a) => a);
No need to do a join if you only need data from one of the tables. You can apply a filter instead:
var q = entities.Activities.Where(a =>
entities.Phases.Any(p => a.PhaseId == p.Id && p.Name == "Preplanning"));

Sqlite Query replacing a column with a column from another table

I have 2 tables, one is indexing the other.
I am querying Table#1, and it has one column (string) that has an ID in it that corresponds to a unique row in Table#2. Im trying to write a query in Sqlite that allows me to retrieve the value from Table#2 if the column value in Table#1 is not an empty string.
Kinda like:
"SELECT TMake,TModel,TTrim,IYear,[%q] AS TPart1 FROM AppGuide WHERE TPart1 != ''"
But instead of retrieving the Index value (TPart1) Id like to get the string from Table#2.
Is this possible?
Any help is appreciated.
You could use a correlated subquery:
SELECT TMake,
TModel,
...,
(SELECT stringvalue
FROM Table2
WHERE Table2.ID = Table1.TPart1)
FROM Table1
WHERE Table1.TPart1 != ''
However, these are rather slow to execute, so you'd better use a join (this returns exactly the same result):
SELECT Table1.TMake,
Table1.TModel,
...,
Table2.stringvalue
FROM Table1 LEFT JOIN Table2 ON Table1.TPart1 = Table2.ID
WHERE Table1.TPart1 != ''
If you don't want to get records from Table1 that have no matching Table2 record, drop the LEFT.

Resources