I have created a query in PLSQL to search customer records from the tables. But still has some limitations. In the &CUSTOMER_ID Search field If I Put IN% OR DL100056* It will search All the details which start with IN or giving the exact DL details as output. I want to search multiple values like in the customer Id field I wanna search DL100056,DL1000365,DL1000652 likewise. But my current query not giving multiple outputs.
SELECT
DISTINCT CUSINFO.CUSTOMER_ID AS DEALER_CODE,
CUSINFO.name AS DEALER_NAME,
CUSINFO.CORPORATE_FORM AS FORM_OF_BUSINESS,
C.corporate_form_desc AS FORM_OF_BUSINESS_DESCRIPTION,
ifsapp.Customer_Info_Address_Api.Get_Address1(CUSINFO.customer_id,1) "ADDRESS 1",
ifsapp.Customer_Info_Address_Api.Get_Address2(CUSINFO.customer_id,1) "ADDRESS 2",
CREDTIN.credit_limit AS CREDIT_LIMIT,
CREDTIN.allowed_due_amount AS ALLOWED_DUE_AMOUNT,
CREDTIN.allowed_due_days AS ALLOWED_DUE_DAYS,
ORDERC.salesman_code AS SALESMAN_CODE,
BDA.name AS SALESMAN_NAME,
ORDERC.discount AS DISCOUNT,
(select LISTAGG(c.value,' / ') within group (order by c.value) from ifsapp.COMM_METHOD c
where c.method_id_db='PHONE' and c.identity=CUSINFO.customer_id ) "Phone",
(select LISTAGG(c.value,' / ') within group (order by c.value) from ifsapp.COMM_METHOD c
where c.method_id_db='MOBILE' and c.identity=CUSINFO.customer_id) "Mobile",
(select LISTAGG(c.value,' / ') within group (order by c.value) from ifsapp.COMM_METHOD c
where c.method_id_db='FAX' and c.identity=CUSINFO.customer_id) "Fax",
CUSINFO.identifier_reference as IDENTIFIER_REFERENCE
FROM
ifsapp.CUSTOMER_INFO CUSINFO
LEFT JOIN
ifsapp.CUSTOMER_INFO_ADDRESS CUSADD ON CUSINFO.customer_id=CUSADD.customer_id
LEFT JOIN
ifsapp.CUSTOMER_INFO_CONTACT CUSCONT ON CUSINFO.customer_id=CUSCONT.customer_id
LEFT JOIN
ifsapp.CUSTOMER_CREDIT_INFO_CUST CREDTIN ON CUSINFO.customer_id=CREDTIN.identity
LEFT JOIN
ifsapp.CUST_ORD_CUSTOMER_ENT ORDERC ON CUSINFO.customer_id=ORDERC.customer_id
LEFT JOIN
ifsapp.Comm_Method COMM ON CUSINFO.customer_id=COMM.customer_id
LEFT JOIN
ifsapp.CORPORATE_FORM C ON CUSINFO.corporate_form=C.CORPORATE_FORM
LEFT JOIN
ifsapp.SALES_PART_SALESMAN_LOV BDA ON ORDERC.salesman_code=BDA.salesman_code
WHERE CUSINFO.CUSTOMER_ID LIKE '&CUSTOMER_ID'
It can't work that way; one option is to use such a query (I don't have your tables so I used Scott's DEPT): it splits parameter values (separated by comma) into rows and uses them as a subquery. So, what you need is lines #3 - 5 (adjusted to your table / column name).
SQL> select deptno, dname, loc
2 from dept
3 where deptno in (select to_number(regexp_substr('&&par_deptno', '[^,]+', 1, level))
4 from dual
5 connect by level <= regexp_count('&&par_deptno', ',') + 1
6 )
7 order by deptno;
Enter value for par_deptno: 10
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
SQL> undefine par_deptno
SQL> /
Enter value for par_deptno: 20,40
DEPTNO DNAME LOC
---------- -------------- -------------
20 RESEARCH DALLAS
40 OPERATIONS BOSTON
SQL>
please format your sql better, it is very difficult to understand the logic behind the query if its is unreadable.
You could try by using LIKE 'DL%'. This will look for all strings starting with DL. Another solution, if the code doesn't always start with 'DL', is using a substring on the code to get the first few characters, then adding '%'
hope this helped
Related
I have several tables that relate to employees and the total amount of sales in dollars and I have to follow these instructions right here:
The company wants to see the total sale amount per sales person (salesman) for all orders. Assume that some online orders do not have any sales person involved. Display the salesman full name and the total sale amount for that employee.
Include also the Total Sale amount for all Orders without involvement of a salesman.
Exclude sales persons whose first name end on y (like Lily or Daisy).
Include only those sales persons who were responsible for more than 4 million dollars in sale.
Sort the result so that bigger sales are shown first.
Note; Do NOT use LIKE operator.
I already have a query statement written in which it shows the employee id instead of the employee name which is what is needed for this query question to be answered properly. In this case the salesman id "," are sales people without names so for ex. sales over the internet therefore no specific name. How do I make it so that I keep the "," but instead show the names of the employee and not their ID Here is the statement:
SELECT NVL(to_char(o.salesman_id), ',') AS "Emp Name", RPAD(to_char(SUM(i.quantity * i.unit_price),'$999,999,999.99'), 16, ' ') AS "Total Sale"
FROM (orders o
INNER JOIN order_items i ON i.order_id = o.order_id)
GROUP BY o.salesman_id
HAVING SUM(i.quantity * i.unit_price) > 4000000.00
ORDER BY 2 DESC;
Heres the output of the query:
Looks like outer join to me.
I don't have your tables so I'll use Scott's emp to illustrate it.
SQL> select empno, ename from emp where deptno = 10;
EMPNO ENAME
---------- ----------
7782 CLARK
7839 KING
7934 MILLER
I'll use those EMPNO values instead of your 62 and 64 (as displayed on the screenshot). your_query CTE represents output you currently have. Then outer join it with table that contains employee names (emp in my case), but leave , for unknown employees:
SQL> with
2 your_query (emp_name, total_sale) as
3 (select ',' , 100 from dual union all
4 select '7782', 200 from dual union all
5 select '7839', 300 from dual
6 )
7 select nvl(e.ename, q.emp_name) ename,
8 q.total_sale
9 from your_query q left join emp e on q.emp_name = to_char(e.empno);
ENAME TOTAL_SALE
---------- ----------
CLARK 200
KING 300
, 100
SQL>
My query looks like below with the foll. output
Current Output
Role Cases prepped % Completed
State Member 1 10 5 50%
State Member 2 10 7 70%
State President 10 2 20%
Summary 30 14 46.6%
Output Expected
Role Cases prepped % Completed
State President 10 2 20%
State Member 1 10 5 50%
State Member 2 10 7 70%
Summary 30 14 46%
Roles table
id name
30 State President
40 State Member
This is my query,
SELECT COALESCE(ROLE, 'Summary') ROLE,
count(*) AS cases,
SUM(CASE WHEN PREPARED = 'Y' THEN 1
ELSE 0
END) AS prepped,
round(avg(case when prepared = 'Y' then 100 else 0 end),2)||'%' as % Completed
FROM
(SELECT CASE
WHEN r.id = 30 THEN r.name
ELSE r.name || ' ' || u.case_member_id
END AS ROLE,
bi.prepared
FROM cases c
LEFT JOIN case_inventory ci ON ci.case_id = c.id
AND c.id = ci.case_id
AND c.delete_date IS NULL
AND ci.case_id =40
Left JOIN users u ON ci.assigned_to = u.id
Left JOIN ROLES r ON u.role_id = r.id
Left JOIN user_cases_map uc ON c.id = uc.case_id
AND uc.id = 1572919346)
GROUP BY ROLLUP (ROLE);
I now want to order the rows with respect to the role. The 1st record should be the State president and then followed by state memebr 1. state member 2. and so on. I tried to have an order by in the inner clause but it did not help. It doesnt have any effect. Adding in the outer select also doesnt change anything. Any help highly appreciated. Thank you.
You could do something like this. I don't have your input data, so I used SCOTT.EMP instead.
Notice a few things. I grouped by JOB, and I used GROUPING(JOB) both in SELECT (to add the label TOTAL for the summary row) and in ORDER BY. Since I reuse the column name JOB in SELECT (for the output column), in ORDER BY I must be careful to qualify the column name JOB (to make it clear I am referring to the input table column, not to the column in SELECT - which would be the default if column names in ORDER BY were not qualified). The need to qualify column names in ORDER BY, then, forced me to alias the table in the FROM clause (otherwise I would have had to carry the full table name everywhere).
Using the GROUPING function in SELECT (rather than NVL) is particularly important if JOB can be null. You don't want the group for null job to be labeled TOTAL - you only want that for the rollup row. This point confuses even a lot of very advanced programmers.
I show how you can "manually" decide the order: PRESIDENT first, then MANAGER, and then all other jobs (ordered alphabetically). If you have the order of priority saved somewhere, for example in a table, you can join to that table and use the ordering column instead of the "manual" CASE expression in my query.
select case grouping(job) when 0 then job else 'TOTAL' end as job
, sum(sal) as total_salary
from scott.emp e
group by rollup(job)
order by grouping(e.job) -- to get the total in the last row
, case e.job when 'PRESIDENT' then 1 when 'MANAGER' then 2 end
, e.job
;
JOB TOTAL_SALARY
--------- ------------
PRESIDENT 5000
MANAGER 8275
ANALYST 6000
CLERK 4150
SALESMAN 5600
TOTAL 29025
My query looks like below with the foll. output
Current Output
Role Cases prepped % Completed
State Member 1 10 5 50%
State Member 2 10 7 70%
State President 10 2 20%
Summary 30 14 46.6%
Output Expected
Role Cases prepped % Completed
State President 10 2 20%
State Member 1 10 5 50%
State Member 2 10 7 70%
Summary 30 14 46%
Roles table
id name
30 State President
40 State Member
This is my query,
SELECT COALESCE(ROLE, 'Summary') ROLE,
count(*) AS cases,
SUM(CASE WHEN PREPARED = 'Y' THEN 1
ELSE 0
END) AS prepped,
round(avg(case when prepared = 'Y' then 100 else 0 end),2)||'%' as % Completed
FROM
(SELECT CASE
WHEN r.id = 30 THEN r.name
ELSE r.name || ' ' || u.case_member_id
END AS ROLE,
bi.prepared
FROM cases c
LEFT JOIN case_inventory ci ON ci.case_id = c.id
AND c.id = ci.case_id
AND c.delete_date IS NULL
AND ci.case_id =40
Left JOIN users u ON ci.assigned_to = u.id
Left JOIN ROLES r ON u.role_id = r.id
Left JOIN user_cases_map uc ON c.id = uc.case_id
AND uc.id = 1572919346)
GROUP BY ROLLUP (ROLE);
I now want to order the rows with respect to the role. The 1st record should be the State president and then followed by state memebr 1. state member 2. and so on. I tried to have an order by in the inner clause but it did not help. It doesnt have any effect. Adding in the outer select also doesnt change anything. Any help highly appreciated. Thank you.
You could do something like this. I don't have your input data, so I used SCOTT.EMP instead.
Notice a few things. I grouped by JOB, and I used GROUPING(JOB) both in SELECT (to add the label TOTAL for the summary row) and in ORDER BY. Since I reuse the column name JOB in SELECT (for the output column), in ORDER BY I must be careful to qualify the column name JOB (to make it clear I am referring to the input table column, not to the column in SELECT - which would be the default if column names in ORDER BY were not qualified). The need to qualify column names in ORDER BY, then, forced me to alias the table in the FROM clause (otherwise I would have had to carry the full table name everywhere).
Using the GROUPING function in SELECT (rather than NVL) is particularly important if JOB can be null. You don't want the group for null job to be labeled TOTAL - you only want that for the rollup row. This point confuses even a lot of very advanced programmers.
I show how you can "manually" decide the order: PRESIDENT first, then MANAGER, and then all other jobs (ordered alphabetically). If you have the order of priority saved somewhere, for example in a table, you can join to that table and use the ordering column instead of the "manual" CASE expression in my query.
select case grouping(job) when 0 then job else 'TOTAL' end as job
, sum(sal) as total_salary
from scott.emp e
group by rollup(job)
order by grouping(e.job) -- to get the total in the last row
, case e.job when 'PRESIDENT' then 1 when 'MANAGER' then 2 end
, e.job
;
JOB TOTAL_SALARY
--------- ------------
PRESIDENT 5000
MANAGER 8275
ANALYST 6000
CLERK 4150
SALESMAN 5600
TOTAL 29025
I need to run a query like below but it doesn't recognize SHOWNDATE. Why this is happening?
The query was simplified to be clear:
select PYNAME,
SHOWNDATE=(SELECT MAX(OUTCOMETIME) FROM A where A.ID=B.ID),
count(PYSUBJECTID)
from B
group by PYNAME,
SHOWNDATE
I think On Select clause write AS SHOWNDATE
SHOWNDATE = is not right.
select
PYNAME,
(SELECT MAX(OUTCOMETIME) FROM A where A.ID=B.ID) AS SHOWNDATE,
count(PYSUBJECTID)
from B
group by PYNAME,SHOWNDATE
Here's an example based on Scott's schema which shows how to do that:
SQL> select b.deptno,
2 (select max(a.sal) from emp a where b.deptno = a.deptno) as showsal,
3 count(b.empno)
4 from emp b
5 group by b.deptno;
DEPTNO SHOWSAL COUNT(B.EMPNO)
---------- ---------- --------------
30 2850 6
20 3000 3
10 5000 3
SQL>
Or, applied to your query:
select b.pyname,
(select max(a.outcometime) from a where a.id = b.id) showndate,
count(b.pysubjectid)
from b
group by b.pyname;
Don't forget to apply table aliases to all columns!
ALIAS (in this case SHOWNDATE) is not a valid identifier but it is for the result set from the subquery. ALIASES are used for convenience...no one wants "SELECT MAX(OUTCOMETIME) FROM A where A.ID=B.ID" as column name.
select
PYNAME
,SHOWNDATE
,COUNT
from (
select PYNAME
,(SELECT MAX(OUTCOMETIME) FROM A where A.ID=B.ID) SHOWNDATE
,count(PYSUBJECTID) COUNT
from B
Group by PYNAME
)
group by PYNAME
,SHOWNDATE
,COUNT
I have a table that i have to work with which unfortunately is not very well designed. The table lists existing products
that have matched to other products. There are two types of matches: a match to a main category product and a match to an alternative category product.
Whenever there is a match, the ID of that match is populated in the relevant column in the table as shown below in PRODUCT_MATCH. So in each product row, there will be a PRODUCT_ID specified in PRODUCT_MAIN_CATEGORY_ID or PRODUCT_ALTERNATIVE_CATEGORY_ID but never both.
PRODUCT
PRODUCT_ID PRODUCT_CATEGORY PRODUCT_SERIAL_NO
1001 Book XSDAD132
1002 MP3 X348023948
1003 DVD 5234234023948
2003 CD SDRX83489
2002 Video 23423879JJ0
PRODUCT_MATCH
PRODUCT_MATCH_ID, PRODUCT_ID, MAIN_CATEGORY_ID, ALTERNATIVE_CATEGORY_ID, PRODUCT_CATEGORY
1 1001 1002 Book
2 1001 1003 Book
3 1002 1004 Book
4 2002 1002 Video
5 2002 1003 Video
6 2002 1001 Video
7 2002 1002 Video
8 1003 2003 DVD
I have to read the PRODUCT_MATCH table so that if there is a match on MAIN_CATEGORY_ID I display the ID, or if there is an ALTERNATIVE_CATEGORY_ID i have to display the product_id and the serial number of the product id.
I have written the following query to display the results
select product_id,
cast(collect(coalesce(MAIN_CATEGORY_ID,
decode(ALTERNATIVE_CATEGORY_ID,null,null, ALTERNATIVE_CATEGORY_ID || '-' || PRODUCT_CATEGORY))) as myType) as product_matches
from product_match
group by product_id
Note: MyType is defined as a table of varchar(2000)
The query will either use MAIN_CATEGORY_ID if it is not null otherwise it will use the value in ALTERNATIVE_CATEGORY_ID to build the output. I want to change this so that it displays the product_id concatenated with the product_serial_no from the PRODUCT number whenever the coalesce function uses the ALTENATIVE_CATEGORY_ID value. This will require a join with the PRODUCT table.
Basically the output I would like to achieve would look like this:
PRODUCT_ID PRODUCT_MATCHES
-----------------------------------
1001 1002,DVD-5234234023948
1002 1004
2002 MP3-X348023948, 1003, 1001, 1002
1003 CD-SDRX83489
I know that i can simply join the tables but it is not as simple as that. The problem is that i only want to use the join if ALTERNATIVE_CATEGORY_ID is used. This means that a simple join will affect the results for when MAIN_CATEGORY_ID is used.
select
pm.product_id,
cast(
collect(
coalesce(
pm.MAIN_CATEGORY_ID,
pm.ALTERNATIVE_CATEGORY_ID || '-' || pr.PRODUCT_SERIAL_NO
)
) as myType
) as product_matches
from
product_match pm
left join PRODUCT pr
on pr.PRODUCT_ID = pm.ALTERNATIVE_CATEGORY_ID
group by
pm.product_id
I think LISTAGG() or WM_CONCAT() functions is what you are looking for as you wrote that you have table not nested table or collection. Collect will return a collection and mostly used with PL/SQL datatypes not with simple tables. The LISTAGG() or WM_CONCAT() will concatenate the values into a single string exactly as in your example.
Sorry, I will not add any queries as your output is very confusing to me. I see only Book matches to product_id = 1001, not DVD and other things. It would be nice if you created sample data using SQL Fiddle or simply create tables and insert. Please do this in the future.
This worked for me - the emp_test is exact copy of scott.emp table:
ALTERE TABLE emp_test MODIFY ename VARCHAR2(3000);
Update emp_test set ename = rpad(ename, 3000, ' '); Commit;
SELECT deptno
, LISTAGG(TRIM(SUBSTR(ename, 1, 3000)), ',') WITHIN GROUP (ORDER BY ename) AS employees
, count(*) total_emps
FROM emp_test
GROUP BY deptno
/
SELECT deptno
, WM_CONCAT(TRIM(SUBSTR(ename, 1, 3000))) AS employees
, count(*) total_emps
FROM emp_test
GROUP BY deptno
/