create from select(Query error) - sql

create table1 as SELECT from c.Name, Value, Qtr, Value as SUM(Value)
from User.Pofile a,pet_dsa_qtr_table b,User.Count c,User.Service d
WHERE Category = 'PROFESSIONAL' and Item_Name = 'PROF_PKT_RECVD' and
convert(char(32),d.User_Id) = c.Name and Service_Name_Cd = 2
and Status = 2 and d.User_Id *= a.User_Id and c.Period = b.Period
and Module = 'ACCT_TRADES' and Type in ('EQ','OPTN')
GROUP BY Name, Item_Value,
Qtr HAVING SUM(Value) >= 10000 and Item_Value in ('0', NULL);
The above was a query that was created by me as an equivalent for sybase.Can anyone help me in correcting this query

You have some quite serious syntax inconsistencies in your query which I have tried to correct (with guesswork as you haven't provided a table structure). e.g. In the select list you select "Value" but in the GROUP BY you group on "Item_Value" etc.
You also need to fully qualify your columns, some you qualify, some (like "Module" and "Type" etc) you don't.
You might also want to add a storage clause too.
Here is my best educated guess at what you are trying to achieve:
CREATE TABLE table1
AS
SELECT c.Name,
Item_Value,
Qtr,
SUM(Value) as "SUM_Value"
FROM User.Pofile a
pet_dsa_qtr_table b,
User.Count c,
User.Service d
WHERE Category = 'PROFESSIONAL'
AND Item_Name = 'PROF_PKT_RECVD'
AND TO_CHAR(d.User_Id) = c.Name
AND Service_Name_Cd = 2
AND Status = 2
AND d.User_Id = a.User_Id(+)
AND c.Period = b.Period
AND Module = 'ACCT_TRADES'
AND Type in ('EQ','OPTN')
GROUP BY c.Name,
Item_Value,
Qtr
HAVING (SUM(Value) >= 10000
AND NVL(Item_Value, '0') = '0');

Related

SUBQUERY WITH SAME TABLE

I have a table that contains :
ID_Magasin: 001 for wharehouse, c01 for a magasin1, c02 for magasin 2, ..
Qte_Physique: the quantity number of an article
id_article: code article
lib_article: article designation
I want a query first, bring all the quantity of articles for each magasin.
second, in the same query I want to add a new column to display the quantity of the same article in the datawherhouse.
If I understand correctly, you can do this with a window function:
select d.*
from (select d.*,
sum(case when id_magasin = '001' then Qte_Physique else 0 end) over (partition by id_article) as wharehouse_qte
from dispo d
) d
where id_magasin <> '001';
Your subquery is not correlated to the main query. I.e. it is lacking the condition which product to look at.
select
gq_depot,
gq_article,
gq_physique,
(
select warehouse.gq_physique
from dispo warehouse
where warehouse.gq_depot = '001'
and warehouse.gq_article = magasin.gq_article
) as wh_physique
from dispo magasin
where gq_depot <> '001'
order by gq_depot, gq_article;
You can do the same with a join:
select
magasin.gq_depot,
magasin.gq_article,
magasin.gq_physique,
warehouse.gq_physique as wh_physique
from dispo magasin
left join dispo warehouse on warehouse.gq_article = magasin.gq_article
and warehouse.gq_depot = '001'
where magasin.gq_depot <> '001'
order by magasin.gq_depot, magasin.gq_article;
For readability you may use WITH clauses, if your DBMS features them:
with warehouse as (select * from dispo where gq_depot = '001')
, magasin as (select * from dispo where gq_depot <> '001')
select
magasin.gq_depot,
magasin.gq_article,
magasin.gq_physique,
warehouse.gq_physique as wh_physique
from magasin
left join warehouse on warehouse.gq_article = magasin.gq_article
order by magasin.gq_depot, magasin.gq_article;
Above queries only work correctly, if gq_depot + gq_article are unique in the table (e.g. constituting the primary key). Otherwise you'd need aggregation to get total gq_physique per gq_depot + gq_article.

Should a subquery on a join use tables from an outer query in the where clause?

I need to add a subquery to a join, because one payment can have more than one allotment, so I only need to account for the first match (where rownum = 1).
However, I'm not sure if adding pmt from the outer query to the subquery on the allotment join is best.
Should I be doing this differently in the event of performance hits, etc.. ?
SELECT
pmt.payment_uid,
alt.allotment_uid,
FROM
payment pmt
/* HERE: is the reference to pmt.pay_key and pmt.client_id
incorrect in the below subquery? */
INNER JOIN allotment alc ON alt.allotment_uid = (
SELECT
allotment_uid
FROM
allotment
WHERE
pay_key = pmt.pay_key
AND
pay_code = 'xyz'
AND
deleted = 'N'
AND
client_id = pmt.client_id
AND
ROWNUM = 1
)
WHERE
AND
pmt.deleted = 'N'
AND
pmt.date_paid >= TO_DATE('2017-07-01')
AND
pmt.date_paid < TO_DATE('2017-10-01') + 1;
It's difficult to identify the performance issue in your query without seeing an explain plan output. You query does seem to do an additional SELECT on the allotment for every record from the main query.
Here is a version which doesn't use correlated sub query. Obviously I haven't been able to test it. It does a simple join in and then filters all records except one of the allotments. Hope this helps.
WITH v_payment
AS
(
SELECT
pmt.payment_uid,
alt.allotment_uid,
ROW_NUMBER () OVER(PARTITION BY allotment_id) r_num
FROM
payment pmt JOIN allotment alt
ON (pmt.pay_key = alt.pay_key AND
pmt.client_id = alt.client_id)
WHERE pmt.deleted = 'N' AND
pmt.date_paid >= TO_DATE('2017-07-01') AND
pmt.date_paid < TO_DATE('2017-10-01') + 1 AND
alt.pay_code = 'xyz' AND
alt.deleted = 'N'
)
SELECT payment_uid,
allotment_uid
FROM v_payment
WHERE r_num = 1;
Let's know how this performs!
You can phrase the query that way. I would be more likely to do:
SELECT . . .
FROM payment p INNER JOIN
(SELECT a.*,
ROW_NUMBER() OVER (PARTITION BY pay_key, client_id
ORDER BY allotment_uid
) as seqnum
FROM allotment a
WHERE pay_code = 'xyz' AND deleted = 'N'
) a
ON a.pay_key = p.pay_key AND a.client_id = p.client_id AND
seqnum = 1
WHERE p.deleted = 'N' AND
p.date_paid >= DATE '2017-07-01' AND
p.date_paid < (DATE '2017-10-01') + 1;

select only distinct value from one column

I am displaying three fields from my query, and I want to display a distinct banking_no. I still want to display the other fields even they are not distinct. Please help.
SELECT C.RECEIPT_OFFICE_PREFIX, B.BANKING_NO, B.STATUS_CD
FROM TControl B, TComponent C
WHERE C.DEPOSIT_BANK_ACCT = 'xxx-xxxxxx-xxxxx'
AND B.BANKING_NO = C.BANKING_NO
AND B.COMPANY_ID = C.COMPANY_ID
AND B.RECEIPT_OFFICE_PREFIX = C.RECEIPT_OFFICE_PREFIX
AND B.STATUS_CD != 'C'
ORDER BY B.BANKING_NO
I am using Sybase ASE 12.5
More recent versions of Sybase support row_number(). You would use it in a subquery like this:
SELECT RECEIPT_OFFICE_PREFIX, BANKING_NO, STATUS_CD
FROM (SELECT C.RECEIPT_OFFICE_PREFIX, B.BANKING_NO, B.STATUS_CD,
ROW_NUMBER() OVER (PARTITION BY B.BANKING_NO ORDER BY B.BANKING_NO) as seqnum
FROM TControl B JOIN
TComponent C
ON B.BANKING_NO = C.BANKING_NO AND B.COMPANY_ID = C.COMPANY_ID
WHERE C.DEPOSIT_BANK_ACCT = 'xxx-xxxxxx-xxxxx' AND
B.RECEIPT_OFFICE_PREFIX = C.RECEIPT_OFFICE_PREFIX AND
B.STATUS_CD != 'C'
) BC
WHERE seqnum = 1
ORDER BY BANKING_NO;
What you want may not be called distint. If the rest of data is the same just using a DISTINCT will do. However if data may be different you need to tell what result should the database choose. the first row? the last row?
If you do not mind just use;
SELECT DISTINCT MAX(C.RECEIPT_OFFICE_PREFIX), B.BANKING_NO, MAX(B.STATUS_CD)
FROM TControl B, TComponent C
WHERE C.DEPOSIT_BANK_ACCT = 'xxx-xxxxxx-xxxxx'
AND B.BANKING_NO = C.BANKING_NO
AND B.COMPANY_ID = C.COMPANY_ID
AND B.RECEIPT_OFFICE_PREFIX = C.RECEIPT_OFFICE_PREFIX
AND B.STATUS_CD != 'C'
GROUP BY B.BANKING_NO
In you need to choose one row use Gordon solution.

How to replace a NULL when a COUNT(*) returns NULL in DB2

I have a query:
SELECT A.AHSHMT AS SHIPMENT, A.AHVNAM AS VENDOR_NAME, D.UNITS_SHIPPED, D.ADPON AS PO, B.NUMBER_OF_CASES_ON_TRANSIT, C.NUMBER_OF_CASES_RECEIVED FROM AHASNF00 A
INNER JOIN (SELECT IDSHMT, COUNT(*) AS NUMBER_OF_CASES_ON_TRANSIT FROM IDCASE00 WHERE IDSTAT = '01' GROUP BY IDSHMT) B
ON (A.AHSHMT = B.IDSHMT)
LEFT JOIN (SELECT IDSHMT, (COUNT(*) AS NUMBER_OF_CASES_RECEIVED FROM IDCASE00 WHERE IDSTAT = '10' GROUP BY IDSHMT) C
ON (A.AHSHMT = C.IDSHMT)
INNER JOIN (SELECT ADSHMT, ADPON, SUM(ADUNSH) AS UNITS_SHIPPED FROM ADASNF00 GROUP BY ADSHMT, ADPON) D
ON (A.AHSHMT = D.ADSHMT)
WHERE A.AHSHMT = '540041134';
On the first JOIN statement I have a COUNT(*), on this count sometimes I will get NULL. I need to replace this with a "0-zero", I know think I know how to do it in SQL
ISNULL(COUNT(*), 0)
But this doesn't work for DB2, how can I accomplish this? All your help is really appreciate it.
Wrap a COALESCE around each of the nullable totals in your SELECT list:
SELECT A.AHSHMT AS SHIPMENT,
A.AHVNAM AS VENDOR_NAME,
COALESCE( D.UNITS_SHIPPED, 0 ) AS UNITS_SHIPPED,
D.ADPON AS PO,
COALESCE( B.NUMBER_OF_CASES_ON_TRANSIT, 0 ) AS NUMBER_OF_CASES_ON_TRANSIT,
COALESCE( C.NUMBER_OF_CASES_RECEIVED, 0 ) AS NUMBER_OF_CASES_RECEIVED
FROM ...
The inner joins you're using for expressions B and D mean that you will only receive rows from A that have one or more cases in transit (expression B) and have one or more POs in expression D. Is that the way you want your query to work?
Instead of using ISNULL(COUNT(*), 0),
try using COALESCE(COUNT(*),0)
use IFNULL(COUNT(*), 0) for DB2

I want SQLplus count(*) to return zero-values

I'm using Oracle 10.2 and have the following query:
select h.company, count(*)
from history h
where h.status = '2'
and h.substatus = '0'
and h.timestamp > '2012-01-01'
and h.timestamp < '2012-02-01'
group by h.company
having (h.company = 'AAA')
or (h.company = 'BBB')
or (h.company = 'CCC')
order by h.company
This will count the amount of times any customer from the companies AAA, BBB or CCC has reached a specific point (status = 2).
Presume no (zero) customers from BBB did so, the result will come back with 2 rows of count(AAA and CCC).
What I want: I wish for the query to return me rows for all 3 companies, even tho the count is zero.
Sorry for the odd layout of the query. It's made to work with MS Excel as well.
Edit: Sorry.. Too little caffeine. changed "Customer" in the later half of the query to "Company".
Clarification: A customer is made unique by combining "h.company" and "h.customer" (or by using the same method in customer-table (customer c), like "c.company" and "c.customer"
Edit 2: Updated code.
select c.company, count(*)
from companyregister c
left join history h on h.company = c.company
where h.status = '2'
and h.substatus = '0'
and h.timestamp > '2012-01-01'
and h.timestamp < '2012-02-01'
group by c.company
having (c.company = 'AAA')
or (c.company = 'BBB')
or (c.company = 'CCC')
order by c.company
Both sets of code from above will yield two rows as follows:
AAA 630
CCC 3020
I would like to have BBB represented, but since they have zero rows in history, they don't show.
Make a left join on the customer table. I don't know what you have named it, but like this:
select c.company, count(h.customer)
from customer as c
left join history as h on h.customer = c.customer
...
Another alternative is to use a condition when counting. I'm not sure if there is any other condition that you need along with the status, but something liket this:
select company, sum(case status when '2' then 1 else 0 end)
from history
where substatus = '0'
and timestamp > '2012-01-01'
and timestamp < '2012-02-01'
and customer in ('AAA', 'BBB', 'CCC')
group by customer
order by customer