SQL change all items - select

How can I select all items which start with an i, instead of Items.ItemCode = '107669'
SELECT p.ProjectNr AS Production,
gbkmut.oms25 AS Description,
(CASE
WHEN SUM(gbkmut.aantal) < 0 AND gbkmut.transsubtype <> 'J'
THEN -SUM(gbkmut.aantal)
ELSE SUM(gbkmut.aantal)
END) AS Quantity,
gbkmut.warehouse AS Warehouse,
gbkmut.id AS RecordNum
FROM PrProject p
JOIN gbkmut ON p.ProjectNr=gbkmut.project
AND gbkmut.bud_vers='MRP' AND gbkmut.transtype='B'
AND gbkmut.freefield1='P'
AND gbkmut.transsubtype IN ('A','B','J')
JOIN Items ON Items.ItemCode=gbkmut.artcode
AND Items.GLAccountDistribution=gbkmut.reknr
WHERE p.Type='P'
AND Items.ItemCode = '107669'
AND gbkmut.afldat >= {d '2019-01-01'}
AND gbkmut.afldat <= {d '2019-12-31'}
GROUP BY p.ProjectNr, gbkmut.oms25, gbkmut.warehouse, gbkmut.afldat, gbkmut.transsubtype, gbkmut.id
ORDER BY p.ProjectNR

Wont work...
SELECT p.ProjectNr AS Production, gbkmut.oms25 AS Description, (CASE WHEN SUM(gbkmut.aantal) < 0 AND gbkmut.transsubtype <> 'J' THEN -SUM(gbkmut.aantal) ELSE SUM(gbkmut.aantal) END) AS Quantity, gbkmut.warehouse AS Warehouse, gbkmut.id AS RecordNum FROM PrProject p JOIN gbkmut ON p.ProjectNr=gbkmut.project AND gbkmut.bud_vers='MRP' AND gbkmut.transtype='B' AND gbkmut.freefield1='P'
AND gbkmut.transsubtype IN ('A','B','J') JOIN Items ON Items.ItemCode=gbkmut.artcode AND Items.GLAccountDistribution=gbkmut.reknr WHERE p.Type='P' **like Items.ItemCode = 'i%'**
AND gbkmut.afldat >= {d '2019-01-01'} AND gbkmut.afldat <= {d '2019-12-31'} GROUP BY p.ProjectNr, gbkmut.oms25, gbkmut.warehouse, gbkmut.afldat, gbkmut.transsubtype, gbkmut.id ORDER BY p.ProjectNR

Related

Query returns more than one row returned by a subquery used as an expression although I am positive it is just one

I have a payment table with one row is a payment record per an account. The first payment is usually the downpayment.
What I need is to add a column which flags 1 if it is the first payment per an account and 0 if it is not. I came up with the ugly query but it throws an error about duplicated rows.
SELECT o.*,
CASE
WHEN o.concat = (SELECT DISTINCT ac.id
|| '-'
|| e.DATE :: DATE AS concant
FROM payment AS e
left join (SELECT id,
alias
FROM account) ac
ON ac.alias = e.account_alias
WHERE e.DATE :: DATE = (SELECT Min(e2.DATE :: DATE)
FROM payment AS e2
WHERE
e2.account_alias = e.account_alias)
AND ac.id BETWEEN 600 AND 800) THEN 1
ELSE 0
END
FROM (SELECT a.id AS account_id,
p.account_alias,
SUM(p.amount) AS amount,
p.DATE :: DATE AS payment_date,
a.id
|| '-'
|| p.DATE :: DATE AS concant
FROM payment p
left join (SELECT id,
alias
FROM account) a
ON p.account_alias = a.alias
WHERE a.id BETWEEN 600 AND 800
GROUP BY a.id,
p.account_alias,
payment_date
ORDER BY a.id,
payment_date ASC) o
I think your repeated query (and thus the IN or =) isn't need at all.
To flag the first payment, you can calculate the the first date and use that to flag the row in the final select.
SELECT o.*,
o.payment_date = min_date as is_first_payment
FROM (SELECT a.id AS account_id,
p.account_alias,
SUM(p.amount) AS amount,
p.date::date AS payment_date,
min(p.date::date) over (partition by a.id, a.alias) as min_date
FROM payment p
left join account a
ON p.account_alias = a.alias
WHERE a.id BETWEEN 600 AND 800
GROUP BY a.id,
p.account_alias,
payment_date
ORDER BY a.id,
payment_date ASC) o
If you have more then a result for subquery then you could use IN instead of =
CASE
WHEN o.concat IN (SELECT DISTINCT ac.id
|| '-'
|| e.DATE :: DATE AS concant
FROM payment AS e
left join (SELECT id,
alias
FROM account) ac
ON ac.alias = e.account_alias
WHERE e.DATE :: DATE = (SELECT Min(e2.DATE :: DATE)
FROM payment AS e2
WHERE
e2.account_alias = e.account_alias)
AND ac.id BETWEEN 600 AND 800) THEN 1
ELSE 0
END

SUM(CASE WHEN ...) returns a greater number than COUNT(DISTINCT..)

I have written a query in two models, but I can't figure out why the second query returns a greater number than the first one; while the number that the first one, COUNT(DISTINCT...) returns is correct:
WITH types(id) AS (VALUES('{1, 4, 5, 3}'::INTEGER[])),
date_gen64 AS
(
SELECT CAST (generate_series(date '10/1/2017', date '11/15/2017', interval
'1 day') AS date) as days ORDER BY days)
SELECT cl.class_date AS c_date,
count(DISTINCT (CASE WHEN co.id = 1 THEN p.id END)),
count(DISTINCT (CASE WHEN co.id = 2 THEN p.id END))
FROM person p
JOIN envelope e ON e.personID = p.id
JOIN "class" cl on cl.id = p.classID
JOIN course co ON co.id = cl.course_id AND co.id = 1
JOIN types ON cr.type_id = ANY (types.id)
RIGHT JOIN date_gen64 dg ON dg.days = cl.class_date
GROUP BY cl.class_date
ORDER BY cl.class_date
The above query returns 26 but following query returns 27!
The reason why I rewrote it with SUM is that the first query
was too slow. But my question is that why the second one counts more?
WITH types(id) AS (VALUES('{1, 4, 5, 3}'::INTEGER[]))
SELECT tmpcl.days,
SUM(CASE WHEN tmp80.course_id = 1 THEN 1
ELSE 0 END),
SUM(CASE WHEN tmp80.course_id = 2 THEN 1
ELSE 0 END)
FROM (
SELECT CAST (generate_series(date '10/1/2017', date '11/15/2017',
interval '1 day') AS date) as days ORDER BY days) tmpcl
LEFT JOIN (
SELECT DISTINCT p.id AS "person_id",
cl.class_date AS c_date,
co.id AS "course_id"
FROM person p
JOIN envelope e ON e.personID = p.id
JOIN "class" cl on cl.id = p.classID
JOIN course co ON co.id = cl.course_id
JOIN types ON cr.type_id = ANY (types.id)
WHERE co.id IN ( 1 , 2 )
) tmp80 ON tmpcl.days = tmp80.class_date
GROUP BY tmpcl.days
ORDER BY tmpcl.days
You can theoretically have multiple people enrolled in the same class on the same day. Indeed that would seem to be the main point of having classes. So each time there are multiple people assigned to the same class on the same day you can have a higher count than you would in your first query. Does that make sense?
You don't appear to be using p.id in that inner query so simply remove it and your counts should match.
WITH types(id) AS (VALUES('{1, 4, 5, 3}'::INTEGER[]))
SELECT tmpcl.days,
SUM(CASE WHEN tmp80.course_id = 1 THEN 1
ELSE 0 END),
SUM(CASE WHEN tmp80.course_id = 2 THEN 1
ELSE 0 END)
FROM (
SELECT CAST (generate_series(date '10/1/2017', date '11/15/2017',
interval '1 day') AS date) as days ORDER BY days) tmpcl
LEFT JOIN (
SELECT DISTINCT cl.class_date AS c_date,
co.id AS "course_id"
FROM person p
JOIN envelope e ON e.personID = p.id
JOIN "class" cl on cl.id = p.classID
JOIN course co ON co.id = cl.course_id
JOIN types ON cr.type_id = ANY (types.id)
WHERE co.id IN ( 1 , 2 )
) tmp80 ON tmpcl.days = tmp80.class_date
GROUP BY tmpcl.days
ORDER BY tmpcl.days

SQL Query handing Jaspersoft Studio Read Fields

I have this current query. I have tested it on 2 of the same verions of Jaspersoft Studio. When I hit read fields, one instance of the program gives me the columns I want however the other instance is stuck in a loop. I have checked the error logs and there is nothing for me to troubleshoot.
I had theorized it was the query but why would it work in one instance and not the next.
Where can I look to find out what is happening? What are my options?
SELECT
LOCATIONS.ID AS LOCATIONID,
LOCATIONS.NAME AS LOCATIONNAME,
PRODUCTS.REFERENCE,
PRODUCTS.CODE AS BARCODE,
PRODUCTS.NAME AS ITEM_NAME,
STOCKDIARY.ATTRIBUTESETINSTANCE_ID,
ATTRIBUTESETINSTANCE.DESCRIPTION AS ATTINSTANCEDESC,
PRODUCTS.CATEGORY,
TICKETLINES.UNITS,
CATEGORIES.NAME AS CATEGORYNAME,
STOCKDIARY.DATENEW,
STOCKDIARY.REASON,
SUM(CASE WHEN STOCKDIARY.UNITS <0 AND STOCKDIARY.DATENEW >= $P{start_date} AND (STOCKDIARY.DATENEW) <= $P{end_date} THEN STOCKDIARY.UNITS ELSE 0 END) AS UNITSOUT,
SUM(CASE WHEN STOCKDIARY.UNITS >=0 AND STOCKDIARY.DATENEW >= $P{start_date} AND (STOCKDIARY.DATENEW) <= $P{end_date} THEN STOCKDIARY.UNITS ELSE 0 END) AS UNITSIN,
SUM(CASE WHEN STOCKDIARY.DATENEW <= $P{end_date} THEN STOCKDIARY.UNITS ELSE 0 END) AS STOCKTOTALNEW,
SUM(CASE WHEN STOCKDIARY.DATENEW <= $P{start_date} THEN STOCKDIARY.UNITS ELSE 0 END) AS STARTINGBALANCE,
SUM(TICKETLINES.UNITS) AS UNIT
FROM TICKETLINES,
STOCKDIARY
LEFT JOIN
LOCATIONS ON STOCKDIARY.LOCATION = LOCATIONS.ID
INNER JOIN
PRODUCTS ON PRODUCTS.ID = STOCKDIARY.PRODUCT
LEFT JOIN
CATEGORIES ON PRODUCTS.CATEGORY = CATEGORIES.ID
LEFT JOIN
ATTRIBUTESETINSTANCE ON STOCKDIARY.ATTRIBUTESETINSTANCE_ID = ATTRIBUTESETINSTANCE.ID
WHERE products.name LIKE "%"
GROUP BY LOCATIONS.NAME , PRODUCTS.REFERENCE , STOCKDIARY.ATTRIBUTESETINSTANCE_ID , ATTRIBUTESETINSTANCE.DESCRIPTION
ORDER BY PRODUCTS.NAME

how to select top 10 without duplicates

Using SQL Server 2012
I need to select TOP 10 Producer based on a ProducerCode. But the data is messed up, users were entering same Producers just spelled differently and with the same ProducerCode.
So I just need TOP 10, so if the ProducerCode is repeating, I just want to pick the first one in a list.
How can I achieve that?
Sample of my data
;WITH cte_TopWP --T
AS
(
SELECT distinct ProducerCode, Producer,SUM(premium) as NetWrittenPremium,
SUM(CASE WHEN PolicyType = 'New Business' THEN Premium ELSE 0 END) as NewBusiness1,
SUM(CASE WHEN PolicyType = 'Renewal' THEN Premium ELSE 0 END) as Renewal1,
SUM(CASE WHEN PolicyType = 'Rewrite' THEN Premium ELSE 0 END) as Rewrite1
FROM ProductionReportMetrics
WHERE YEAR(EffectiveDate) = 2016 AND TransactionType = 'Policy' AND CompanyLine = 'Arch Insurance Company'--AND ProducerType = 'Wholesaler'
GROUP BY ProducerCode,Producer
)
,
cte_Counts --C
AS
(
SELECT distinct ProducerCode, ProducerName, COUNT (distinct ControlNo) as Submissions2,
SUM(CASE WHEN QuotedPremium IS NOT NULL THEN 1 ELSE 0 END) as Quoted2,
SUM(CASE WHEN Type = 'New Business' AND Status IN ('Bound','Cancelled','Notice of Cancellation') THEN 1 ELSE 0 END ) as NewBusiness2,
SUM(CASE WHEN Type = 'Renewal' AND Status IN ('Bound','Cancelled','Notice of Cancellation') THEN 1 ELSE 0 END ) as Renewal2,
SUM(CASE WHEN Type = 'Rewrite' AND Status IN ('Bound','Cancelled','Notice of Cancellation') THEN 1 ELSE 0 END ) as Rewrite2,
SUM(CASE WHEN Status = 'Declined' THEN 1 ELSE 0 END ) as Declined2
FROM ClearanceReportMetrics
WHERE YEAR(EffectiveDate)=2016 AND CompanyLine = 'Arch Insurance Company'
GROUP BY ProducerCode,ProducerName
)
SELECT top 10 RANK() OVER (ORDER BY NetWrittenPremium desc) as Rank,
t.ProducerCode,
c.ProducerName as 'Producer',
NetWrittenPremium,
t.NewBusiness1,
t.Renewal1,
t.Rewrite1,
c.[NewBusiness2]+c.[Renewal2]+c.[Rewrite2] as PolicyCount,
c.Submissions2,
c.Quoted2,
c.[NewBusiness2],
c.Renewal2,
c.Rewrite2,
c.Declined2
FROM cte_TopWP t --LEFT OUTER JOIN tblProducers p on t.ProducerCode=p.ProducerCode
LEFT OUTER JOIN cte_Counts c ON t.ProducerCode=c.ProducerCode
You should use ROW_NUMBER to fix your issue.
https://msdn.microsoft.com/en-us/library/ms186734.aspx
A good example of this is the following answer:
https://dba.stackexchange.com/a/22198
Here's the code example from the answer.
SELECT * FROM
(
SELECT acss_lookup.ID AS acss_lookupID,
ROW_NUMBER() OVER
(PARTITION BY your_distinct_column ORDER BY any_column_you_think_is_appropriate)
as num,
acss_lookup.product_lookupID AS acssproduct_lookupID,
acss_lookup.region_lookupID AS acssregion_lookupID,
acss_lookup.document_lookupID AS acssdocument_lookupID,
product.ID AS product_ID,
product.parent_productID AS productparent_product_ID,
product.label AS product_label,
product.displayheading AS product_displayheading,
product.displayorder AS product_displayorder,
product.display AS product_display,
product.ignorenewupdate AS product_ignorenewupdate,
product.directlink AS product_directlink,
product.directlinkURL AS product_directlinkURL,
product.shortdescription AS product_shortdescription,
product.logo AS product_logo,
product.thumbnail AS product_thumbnail,
product.content AS product_content,
product.pdf AS product_pdf,
product.language_lookupID AS product_language_lookupID,
document.ID AS document_ID,
document.shortdescription AS document_shortdescription,
document.language_lookupID AS document_language_lookupID,
document.document_note AS document_document_note,
document.displayheading AS document_displayheading
FROM acss_lookup
INNER JOIN product ON (acss_lookup.product_lookupID = product.ID)
INNER JOIN document ON (acss_lookup.document_lookupID = document.ID)
)a
WHERE a.num = 1
ORDER BY product_displayheading ASC;
You could do this:
SELECT ProducerCode, MIN(Producer) AS Producer, ...
GROUP BY ProducerCode

Count distinct column case when/conditional

I'm trying to count the distinct number of ids in a column and this works fine.
COUNT(DISTINCT messages.id) AS link_created
But when I try to count with a conditional, I get a syntax error, what's the proper syntax to add a case when or some other condition to only count the distinct message ids where the messages.link_label is present?
COUNT(DISTINCT messages.id CASE WHEN messages.link_label IS NOT NULL 1 END) AS link_created
My full query looks like this.
#customers = Customer.select("customers.*,
COUNT(DISTINCT recipient_lists.id) messages_sent,
COUNT(DISTINCT messages.id CASE WHEN messages.link_label IS NOT NULL 1 END) AS link_created,
COALESCE(SUM(video_activities.video_watched_count),0) AS watched_count,
COALESCE(SUM(video_activities.response_count),0) AS response_count,
COALESCE(SUM(video_activities.email_opened_count),0) AS email_opened_count,
COALESCE(SUM(CASE WHEN video_activities.video_watched_at IS NOT NULL THEN 1 ELSE 0 END),0) AS unique_watches,
COALESCE(SUM(CASE WHEN video_activities.email_opened_at IS NOT NULL THEN 1 ELSE 0 END),0) AS unique_opens,
COALESCE(SUM(CASE WHEN video_activities.response_count > 0 THEN 1 ELSE 0 END),0) AS unique_responses,
customers.updated_at AS last_login,
SUBSTRING( email from POSITION( '#' in email) + 1 for length(email)) AS company")
.joins("LEFT JOIN messages ON customers.id = messages.customer_id
LEFT JOIN recipient_lists ON messages.id = recipient_lists.message_id AND messages.link_label is NULL
LEFT JOIN video_activities ON messages.id = video_activities.message_id")
.group("customers.id")
Try this:
COUNT(DISTINCT CASE
WHEN messages.link_label IS NOT NULL
THEN messages.id
ELSE NULL END)
AS link_created