combine multiple queries into single query - oracle11g

I have 2 queries and calling a function 2 times I need call the function one time only based on msg_sys_no count and msg_trans_type.
please find the queries mentioned below and provide me the solution for merging into single.
SELECT COUNT(DISTINCT b1.msg_sys_no) INTO A
FROM tra_message b1
WHERE TO_CHAR(b1.msg_when_created,'YYYY-MM-DD') = in_start_date
AND b1.msg_service_provider = in_svc_provider
AND b1.msg_trans_type = 'TRADE1'
AND get_transaction_status_func(b1.msg_sys_no, b1.msg_trans_type) = 'S';
SELECT COUNT(DISTINCT b1.msg_sys_no) INTO B
FROM tra_message b1
WHERE TO_CHAR(b1.msg_when_created,'YYYY-MM-DD') = in_start_date
AND b1.msg_service_provider = in_svc_provider
AND b1.msg_trans_type = 'TRADE2'
AND get_transaction_status_func(b1.msg_sys_no, b1.msg_trans_type) = 'S';

What about something like this:
WITH tra_data
AS (SELECT *
FROM tra_message
WHERE TO_CHAR (msg_when_created, 'YYYY-MM-DD') = in_start_date
AND msg_service_provider = in_svc_provider
AND get_transaction_status_func (msg_sys_no, msg_trans_type) =
'S')
SELECT COUNT (*)
FROM tra_data
WHERE msg_trans_type = 'TRADE1'
UNION
SELECT COUNT (*)
FROM tra_data
WHERE msg_trans_type = 'TRADE2'

The problem is your AND b1.msg_trans_type IN ('TRADE1','TRADE2') condition.
Try something like this:
select COUNT(DISTINCT a) TRADE1,
COUNT(DISTINCT b) TRADE2
into A,B
from (
select case when b1.msg_trans_type = 'TRADE1'
then b1.msg_sys_no
else null end as a,
case when b1.msg_trans_type = 'TRADE2'
then b1.msg_sys_no
else null end as b
FROM tra_message b1
WHERE TO_CHAR(b1.msg_when_created,'YYYY-MM-DD') = in_start_date
AND b1.msg_service_provider = in_svc_provider
AND b1.msg_trans_type IN ('TRADE1','TRADE2')
AND get_transaction_status_func(b1.msg_sys_no, b1.msg_trans_type) = 'S'
);

Related

Query Builder Error in doctrine symfony using where in

I have a raw query which I would like to convert into doctrine ORM. It's basically a query which contains sub query to calculate total count.
SELECT Count(*) AS total_count
FROM (SELECT *
FROM content_item_languages
WHERE default_content_item_id IN (SELECT id AS default_content_item_id
FROM content_item
WHERE content_type = 1
AND is_translated = 0
AND modified_on >=
'$timePeriodStart'
AND is_active = 1)
AND language_id = '$language') AS t
I have written below doctrine ORM but still I am getting error
$em = $this->getEntityManager()->createQueryBuilder();
$totalPostSubselect = $em->addSelect('c.id AS defaultContentItemId')
->from('AppBundle\Entity\ContentItem\ContentItem', 'c')
->andWhere('c.contentType = 1')
->andWhere('c.isTranslated = 0')
->andWhere('c.modifiedOn >= :timeperiod')
->andWhere('c.isActive = :status')
->setParameter('status', 1)
->setParameter('timeperiod', $timePeriodStart)->getDQL();
$em = $this->getEntityManager()->createQueryBuilder();
$defaultSubSelect = $em->addSelect(['*'])
->from('AppBundle\Entity\ContentItem\ContentItemLanguages', 'cl')
->andWhere("cl.defaultContentItemId IN ($totalPostSubselect)")
->andWhere('cl.languageId = :language')
->setParameter('subSelect', $totalPostSubselect)
->setParameter('language', $language)->getDQL();
$em = $this->getEntityManager()->createQueryBuilder();
$mainQuerySelect = $em->addSelect(["count(*) as total_count"])
->from("(".$defaultSubSelect.")", 'AS t')->getQuery();
return $mainQuerySelect->getResult();
Here is the error I got
[Doctrine\ORM\Query\QueryException] [Syntax Error] line 0, col 13: Error: Expected Literal, got '*'
[Doctrine\ORM\Query\QueryException]
SELECT count(*) as total_count FROM (SELECT * FROM
AppBundle\Entity\ContentItem\ContentItemLanguages cl
WHERE (
cl.defaultContentItemId IN (SELECT c.id AS defaultContentItemId
FROM AppBundle\Entity\ContentItem\ContentItem c WHERE
c.contentType = 1 AND
c.isTranslated = 0 AND
c.modifiedOn >= :timeperiod AND c.isActive = :status))
AND cl.languageId = :language) AS t
can anyone suggest, in exactly where I am doing wrong ?
In doctrine query language you can't SELECT *, instead you have to deal with objects. For your example something like:
$mainQuerySelect = $em->addSelect("count(t.id) as total_count")
->from("(".$defaultSubSelect.")", 'AS t')->getQuery();

MS SQL Case in Where Clause testing against NULL or Argument

I have a query against a UDF where I want to allow the user to pass in either ALL or a specific EType.
If they pass in ALL, I want to accept all ETypes where it is not null.
I have searched thru SO for examples and not seem to meet my particular situation.
Where am I going wrong?
Declare
#company varchar(4),
#charge_cov bit,
#EType varchar(8);
set #company = '123'
set #charge_cov =1
set #EType = 'ALL'
select e.emp_id,
dbo.format_emp_number(pd.EN) as EN,
dbo.format_emp_number(pd.MEN) as MEN,
pd.EType
from dbo.employee_payroll_data(NULL) pd
inner join employee e on (e.emp_id=pd.emp_id)
where pd.EType = case when #EType='ALL' then pd.EType
else #EType ) END
and pd.EType is not null
and e.emp_number is not null
and e.charge_cov = 1
and lc.pr_co_code = #company
Try below code:
WHERE (((1 = (CASE WHEN #EType = 'ALL' THEN 1 ELSE 0 END)))
OR ((pd.Etype = (CASE WHEN #EType <> 'ALL' THEN #EType ELSE '' END))))
AND pd.Etype IS NOT NULL

Being DRY in a Sqlite query with CASE statement

In the following (working) query:
SELECT q.id, q.section_id, q.type, q.required, q.condition,
CASE WHEN (t1.text_1 IS NULL) THEN
CASE WHEN ((SELECT t2.text_1 FROM translations t2 WHERE t2.item_id = q.id AND t2.item_model = 'questions' AND t2.language = 'en' LIMIT 1) IS NULL) THEN
(SELECT t3.text_1 FROM translations t3 WHERE t3.item_id = q.id AND t3.item_model = 'questions' LIMIT 1)
ELSE
(SELECT t2.text_1 FROM translations t2 WHERE t2.item_id = q.id AND t2.item_model = 'questions' AND t2.language = 'en' LIMIT 1)
END
ELSE
t1.text_1
END
AS translation
FROM questions q
LEFT JOIN translations t1 ON t1.item_id = q.id
AND t1.item_model = 'questions'
AND t1.language = 'fr'
ORDER BY q.position
You can see that the part (SELECT t2.text_1 FROM translations t2 WHERE t2.item_id = q.id AND t2.item_model = 'questions' AND t2.language = 'en' LIMIT 1) is repeated twice (the first to check if it's null, and the second to get the value).
Could the repeated same query a performance issue (I guess so)?
Is there a better way to rewrite this query, being DRY?
You can replace the inner CASE statement with coalesce() function:
coalesce(SELECT t2.text_1 FROM translations t2 WHERE t2.item_id = q.id AND t2.item_model = 'questions' AND t2.language = 'en' LIMIT 1,
SELECT t3.text_1 FROM translations t3 WHERE t3.item_id = q.id AND t3.item_model = 'questions' LIMIT 1)
From the documenation:
coalesce(X,Y,...)
The coalesce() function returns a copy of its first non-NULL argument,
or NULL if all arguments are NULL. Coalesce() must have at least 2
arguments.
Similar is the ifnull() function.

Query filter assign sub query to one field value

I have stuck in this issue from the last two days.
Please help.
I want to assign the following query .
$qr = "( select subconfigcode.field_subconfigcode_value AS configcode FROM node node LEFT JOIN field_data_field_select_parent_configuratio select_parent_configuratio ON node.nid = select_parent_configuratio.entity_id AND (select_parent_configuratio.entity_type = node AND select_parent_configuratio.deleted = 0) LEFT JOIN node select_parent_configuratio_node ON select_parent_configuratio.field_select_parent_configuratio_nid = select_parent_configuratio_node.nid LEFT JOIN field_data_field_subconfigcode subconfigcode ON select_parent_configuratio_node.nid = subconfigcode.entity_id AND (subconfigcode.entity_type = 'node' AND subconfigcode.deleted = '0') WHERE (( (select_parent_configuratio.field_select_parent_configuratio_nid = node_field_data_field_select_parent_configuratio.nid) )AND(( (node.status = '1') AND (node.type IN ('offering')) ))) ORDER BY node.created DESC, configcode ASC LIMIT 1 OFFSET 0)";
to
one view's field value.
I have used the following code.
function general_views_query_alter(&$view, &$query) {
$qr = " ( select subconfigcode.field_subconfigcode_value AS configcode FROM node node LEFT JOIN field_data_field_select_parent_configuratio select_parent_configuratio ON node.nid = select_parent_configuratio.entity_id AND (select_parent_configuratio.entity_type = node AND select_parent_configuratio.deleted = 0) LEFT JOIN node select_parent_configuratio_node ON select_parent_configuratio.field_select_parent_configuratio_nid = select_parent_configuratio_node.nid LEFT JOIN field_data_field_subconfigcode subconfigcode ON select_parent_configuratio_node.nid = subconfigcode.entity_id AND (subconfigcode.entity_type = 'node' AND subconfigcode.deleted = '0') WHERE (( (select_parent_configuratio.field_select_parent_configuratio_nid = node_field_data_field_select_parent_configuratio.nid) )AND(( (node.status = '1') AND (node.type IN ('offering')) ))) ORDER BY node.created DESC, configcode ASC LIMIT 1 OFFSET 0)";
$query->add_where(1, "node_field_data_field_select_parent_configuratio__field_data_field_subconfigcode.field_subconfigcode_value", $qr);
}
But, it is returning the following where query.
where node_field_data_field_select_parent_configuratio__field_data_field_subconfigcode.field_subconfigcode_value = '( select subconfigcode.field_subconfigcode_value AS configcode FROM node node LEFT JOIN field_data_field_select_parent_configuratio select_parent_configuratio ON node.nid = select_parent_configuratio.entity_id AND (select_parent_configuratio.entity_type = node AND select_parent_configuratio.deleted = 0) LEFT JOIN node select_parent_configuratio_node ON select_parent_configuratio.field_select_parent_configuratio_nid = select_parent_configuratio_node.nid LEFT JOIN field_data_field_subconfigcode subconfigcode ON select_parent_configuratio_node.nid = subconfigcode.entity_id AND (subconfigcode.entity_type = \'node\' AND subconfigcode.deleted = \'0\') WHERE (( (select_parent_configuratio.field_select_parent_configuratio_nid = node_field_data_field_select_parent_configuratio.nid) )AND(( (node.status = \'1\') AND (node.type IN (\'offering\')) ))) ORDER BY node.created DESC, configcode ASC LIMIT 1 OFFSET 0) ')
I want to get query without the single quote assigned for sub query and remove extra slashed added to each value.
Please help.
Answer :
Direct query is not applicable for assignment purpose in the add_where condition.
For that, I have generated the query object using.
function general_views_query_alter(&$view, &$query) {
$subQuery = db_select('node', 'node'); $subQuery->leftJoin('field_data_field_select_parent_configuratio', 'select_parent_configuratio ', 'node.nid = select_parent_configuratio .entity_id');
$subQuery->condition('select_parent_configuratio.entity_type', 'node', '=');
$subQuery->condition('select_parent_configuratio.deleted', '0', '=');
$subQuery->leftJoin('node', 'select_parent_configuratio_node', 'select_parent_configuratio.field_select_parent_configuratio_nid = select_parent_configuratio_node.nid');
$subQuery->leftJoin('field_data_field_subconfigcode', 'subconfigcode', 'select_parent_configuratio_node.nid = subconfigcode.entity_id');
$subQuery->condition('subconfigcode.entity_type', 'node', '=');
$subQuery->condition('subconfigcode.deleted', '0', '=');
$subQuery->where("select_parent_configuratio.field_select_parent_configuratio_nid = node_field_data_field_select_parent_configuratio.nid");
$subQuery->condition('node.status', "1", '=');
$subQuery->condition('node.type', array('offering'), 'IN');
$subQuery->orderBy('configcode');
$subQuery->addField('subconfigcode', 'field_subconfigcode_value', 'configcode');
//$subQuery->range(0, 1);
$query->add_where($group,'node_field_data_field_select_parent_configuratio__field_data_field_subconfigcode.field_subconfigcode_value',$subQuery,'in');
}
Using this, I am able to generate it the query and assignment to value of the variable.

Comparing Multiple Values from one table to Multiple Values in another

I have a PL/SQL stored function script I am writing and I have run into a problem.
I need to find ALL Applicants who possess ALL the skills needed for a task and display them.
I have a method where I have individually read in Applicant's skills into a VARCHAR2 string and all the Skills required into another. If I could separate these strings into individual words I could compare the two with LIKE '% <data> %'.
How would I go about this (or what is an alternative method)?
CREATE OR REPLACE FUNCTION FUBARR(num IN NUMBER) RETURN VARCHAR IS
string_position VARCHAR2(128);
string_applicant VARCHAR2(128);
string_results VARCHAR2(128);
BEGIN
string_position := '';
string_applicant := '';
FOR SKILLS_row IN (SELECT sname FROM SNEEDED WHERE pnumber = num)
LOOP
string_position := string_position || SKILLS_row.sname || ' ';
END LOOP;
FOR EVERYBODY_row IN (SELECT UNIQUE anumber FROM SPOSSESSED ORDER BY anumber)
LOOP
FOR APPLICANTS_row IN (SELECT sname FROM SPOSSESSED WHERE SPOSSESSED.anumber = EVERYBODY_row.anumber)
LOOP
string_applicant := string_applicant || APPLICANTS_row.sname || ' ';
END LOOP;
--DBMS_OUTPUT.PUT_LINE(EVERYBODY_row.anumber || ' ' || string_applicant);
--IF blaah != LIKE BLAh
IF
string_applicant := '';
END LOOP;
--DBMS_OUTPUT.PUT_LINE(string_position);
--RETURN (string_position);
RETURN('help');
END FUBARR;
/
why not simply select all spossesed - records, where the number of associated skills of the desired num is equal to the plain number of sneeded - skills of that num:
SELECT *
FROM SPOSSESSED sp
WHERE (SELECT COUNT(*) FROM SNEEDED s
WHERE s.pnumber = num) =
(SELECT COUNT(*) FROM SNEEDED s
JOIN SPOSSESSED p ON p.sname = s.sname
WHERE s.pnumber = num and p.anumber = sp.anumber)
or using the ANY construct:
SELECT sp.anumber, COUNT(*)
FROM SPOSSESSED sp
WHERE sp.sname = ANY (SELECT s.sname FROM SNEEDED s WHERE s.pnumber = num)
GROUP BY sp.anumber

Resources