Join and show latest Event - sql-server-2008

I need to generate a related of all "Tickets" that is open and with status "Analysis",i need to do a join in two tables.
The first one:
SELECT TOP 1000
[nsu_sugestao]
,[num_sugestao_papel]
,[edv_promotor]
FROM [NovoCLIC].[dbo].[Sugestao]
Exemplo of this select:
nsu_sugestao num_sugestao_papel edv_promotor
1 372759 92602045
In this one, num_sugestao_papel is the number of the ticket, edv_promotor is the person the owns it.
The second one:
SELECT TOP 1000
[iClic]
,[iStatus]
,[dtDateCreated]
FROM [NovoCLIC].[dbo].[T_STATUS_CLIC]
Exemple:
iClic iStatus dtDateCreated
1 1 1999-01-25 13:33:00.000
The iClic is the ticket number, the iStatus is the status currently and dtDateCreated.
I need to show all Tickets the the last status is analysis, the status analysis is the number 2 in iStatus column, i don't need the tickets that already are in different numbers than 2.
SELECT TOP 1000 [nsu_sugestao]
-- ,n.num_sugestao_papel
-- ,n.edv_promotor
-- ,s.iStatus
-- ,s.dtDateCreated
-- FROM [NovoCLIC].[dbo].[Sugestao]
-- with
-- select s.dtDateCreated,MAX(s.EventDate)latestDate
-- from [NovoCLIC].[dbo].[T_STATUS_CLIC] s
-- right join [NovoCLIC].[dbo].[T_STATUS_CLIC] s on [NovoCLIC].[dbo].[Sugestao] =
I'm trying something like this, but I'm getting a lot of errors.

Try the code given below and provide us feedback
SELECT
S.[nsu_sugestao]
,S.[num_sugestao_papel]
,S.[edv_promotor]
,T.[iClic]
,T.[iStatus]
,T.[dtDateCreated]
FROM [NovoCLIC].[dbo].[Sugestao] S
INNER JOIN [NovoCLIC].[dbo].[T_STATUS_CLIC] T on S.nsu_sugestao = T.iClic
INNER JOIN (
SELECT
[iClic]
,Max([dtDateCreated]) As LatestDateCreated
FROM
[NovoCLIC].[dbo].[T_STATUS_CLIC]
GROUP BY
[iClic]
) TM ON T.iClic = TM.iClic AND T.dtDateCreated = TM.LatestDateCreated
WHERE
T.iStatus = 2

Related

How select count distinct (unique truckers) without group by function and maybe without using Having (not sure about last)

I have a task, but couldn't solve it:
There are truckers and they have to travel between cities.
We have data of these travels in our database in 2 tables:
trucker_traffic
tt_id (key)
date
starting_point_coordinate
destination_coordinate
traveller_id
event_type ('travel', 'accident')
parent_event_id (For 'accident' event type it's tt_id of the original travel. There might be few accidents within one travel.)
trucker_places
coordinate (key)
country
city
I need SQL query to pull the number of all unique truckers who travelled more than once from or to London city in June 2020.
In the same query pull the number of these travels who got into an accident.
Example of my tries
SELECT
count(distinct(tt.traveller_id)),
FROM trucker_traffic tt
JOIN trucker_places tp
ON tt.starting_point_coordinate = tp.coordinate
OR tt.destination_coordinate = tp.coordinate
WHERE
tp.city = 'London'
AND month(tt.date) = 6
AND year(tt.date) = 2020
GROUP BY tt.traveller_id
HAVING count(tt.tt_id) > 1
But it's select count distinct truckers with grouping and works only if I had one tracker in db
For second part of task (where I have select number of travels with accident - I think that good to use function like this
SUM(if(count(tt_id = parent_event_id),1,0))
But I'm not sure
This is rather complicated, so make sure you do this step by step. WITH clauses help with this.
Steps
Find travels from and to London in June 2020. You can use IN or EXISTS in order to see whether a travel had accidents.
Group the London travels by traveller, count travels and accident travels and only keep those travellers with more than one travel.
Take this result set to count the travellers and sum up their travels.
Query
with london_travels as
(
select
traveller_id,
case when tt_id in
(select parent_event_id from trucker_traffic where event_type = 'accident')
then 1 else 0 end as accident
from trucker_traffic tt
where event_type = 'travel'
and month(tt.date) = 6
and year(tt.date) = 2020
and exists
(
select
from trucker_places tp
where tp.coordinate in (tt.starting_point_coordinate, tt.destination_coordinate)
and tp.city = 'London'
)
)
, london_travellers as
(
select
traveller_id,
count(*) as travels,
sum(accident) as accident_travels
from london_travels
group by traveller_id
having count(*) > 1;
)
select
count(*) as total_travellers,
sum(travels) as total_travels,
sum(accident_travels) as total_accident_travels
from london_travellers;
If your MySQL version doesn't support WITH clauses, you can of course just nest the queries. I.e.
with a as (...), b as (... from a) select * from b;
becomes
select * from (... from (...) a) b;
You say in the request title that you don't want GROUP BY in the query. This is possible, but makes the query more complicated. If you want to do this I leave this as a task for you. Hint: You can select travellers and count in subqueries per traveller.

Getting max revision number from a view is not working as I thought?

Using MySQL 5.6. I have a view that grabs from one main table called listquotes, and a few other items from other tables. The import columns in the table that are also in the view are Quote # and Revision. We might have 5 different revisions of the same quote number, so our table would look like
id .... Quote# Revision
================================
1 1234 1
2 1234 2
3 1234 3
4 1234 4
5 1234 5
Now on my application GUI we have a dropdown that should allow you to only see the most recent revisions of every quote. Here's how I try to do that
SELECT
...columns...
FROM view_allQuoteInfo
LEFT JOIN listcustomers c ON c.id = view_allQuoteInfo.customerId
WHERE 1=1 AND view_allquoteinfo.customerId = 2453 AND view_allquoteinfo.quoteStatusId = 2 AND view_allquoteinfo.Revision = (SELECT max(t.Revision) FROM view_allquoteinfo t WHERE view_allquoteinfo.`Quote #` = t.`Quote #`)
ORDER BY idx DESC
However, this is not giving me the results I want. Here's an analysis for tihs specific customer I did in excel, some quotes that only have one revision are not showing up like 6668 while others like 4730 which has two revisions is working properly
The where clause for the All table in excel is
1=1
AND view_allquoteinfo.customerId = 2453
AND view_allquoteinfo.quoteStatusId = 2
and the clause for the Latest Table is
1=1
AND view_allquoteinfo.customerId = 2453
AND view_allquoteinfo.quoteStatusId = 2
AND view_allquoteinfo.Revision =
(SELECT max(t.Revision)
FROM view_allquoteinfo t
WHERE view_allquoteinfo.`Quote #` = t.`Quote #`)
the only difference being me trying to get the mlatest revision. The logic looks right to me but obviously MySQL is not interpreting it the way I thought it would.
Any clue as to why it's not working or how I would fix it?
I would expect to see quote 6668 revision one and quote 5963 revision 4 in my "Latest" table, while quote 5963 revision 1,2,3 would not be there.
the condition WHERE view_allquoteinfo.Quote # = t.Quote # inside the subqiery is not clear ( t and view_allquoteinfo are the same table)
so try using a join on subquery group by quote
SELECT
...columns...
FROM view_allQuoteInfo
INNER JOIN (
SELECT v.`Quote #` my_quote, max(v.Revision) max_rev
FROM view_allquoteinfo v
GRUP BY v.`Quote #`
) t ON t.my_quote = view_allQuoteInfo.`Quote #`
AND t.max_rev = view_allQuoteInfo.Revision
LEFT JOIN listcustomers c ON c.id = view_allQuoteInfo.customerId
WHERE view_allquoteinfo.customerId = 2453
AND view_allquoteinfo.quoteStatusId = 2
ORDER BY idx DESC
I figured out a way that works for me. When the user wants all quotes, I leave it the way it is.
When the user wants only the latest revisions, I modify my select query to say
SELECT ...., MAX(view_allquoteinfo.Revision) as 'Revision',...
and then I add a
GROUP BY view_allquoteinfo.'Quote #'.

SQL Statement running extreamly Slow

Okay I have look through several posts about SQL running slow and I didn't see anything similar to this, so my apologies if I missed one. I was asked about a month ago to create a view that would allow the user to report what hasn't been billed yet, and the SQL is joining 4 tables together. One is 1.2 million records ish. the rest are between 80K - 250K. (Please note that this should only return around 100 records after the where statements).
SELECT C.Cltnum + '.' + C.CltEng AS [ClientNum],
C.CPPLname,
w.WSCDesc,
MIN(w.Wdate) AS [FirstTDate],
w.WCodeCat,
w.WCodeSub,
SUM(w.Wbilled) AS [Billed],
SUM(w.Whours * w.Wrate) AS [Billable Wip],
sum(ar.[ARProgress]) AS [Progress],
w.Winvnum,
-- dbo.GetInvoiceAmount(w.Winvnum) AS [InvoiceAmount],
SUM(cb.cinvar) AS [AR Balance]
FROM dbo.WIP AS w
--Never join on a select statement
--join BillingAuditCatagoriesT bac on w.WCodeCat = bac.Catagory and w.WCodeSub = bac.Subcatagory
INNER JOIN dbo.Clients AS C ON w.WCltID = C.ID
JOIN dbo.ClientBuckets AS cb on c.cltnum = cb.cltnum
JOIN dbo.AcctsRec AS ar on ar.arapplyto = w.[Winvnum]
-- WHERE w.wcodecat = '1AUDT'
GROUP BY C.Cltnum, C.CltEng, C.CPPLname, w.WCodeCat, w.Wdate, w.Winvnum, w.WCodeSub, w.WSCDesc
so, where I think there may be a problem is that Category is a varchar it is xat, ACT, BID and there are about 15 different Category. this is the same as SubCat. you will notice that there are 3 functions on this and they are GetJamesProgress Which is = (SELECT sum(Amount) From Progress Where inv = w.invnum) and the same with GetInvoiceAmount and GetJamesARBalance. I know that this is bad to do but when I join by invoice number it takes even longer than with out them.
Please help thanks so much!

SQL SUM issues with joins

I got a quite complex query (at least for me).
I want to create a list of users that are ready to be paid. There are 2 conditions that need to be met: order status should be 3 and the total should be more then 50. Currently I got this query (generated with Codeingiter active record):
SELECT `services_payments`.`consultant_id`
, `consultant_userdata`.`iban`
, `consultant_userdata`.`kvk`, `consultant_userdata`.`bic`
, `consultant_userdata`.`bankname`
, SUM(`services_payments`.`amount`) AS amount
FROM (`services_payments`)
JOIN `consultant_userdata`
ON `consultant_userdata`.`user_id` = `services_payments`.`consultant_id`
JOIN `services`
ON `services`.`id` = `services_payments`.`service_id`
WHERE `services`.`status` = 3
AND `services_payments`.`paid` = 0
HAVING `amount` > 50
The services_payments table contains the commissions, consultant_userdata contains the userdata and services keeps the order data. The current query only gives me 1 result while I'm expecting 4 results.
Could someone please tell me what I'm doing wrong and what would be the solution?
For ActiveRecord, rsanchez' answer would be more of
$this->db->group_by('services_payments.consultant_id, consultant_userdata.iban, consultant_userdata.kvk, consultant_userdata.bic, consultant_userdata.bankname');

Using MAX of a field to select a record returns MAX of the table ignores the condition

I'm doing a stored procedure for a report, and I'm trying to get only those records with the highest value of a determined field (accumulated amount), the thing is I can't seem to find the solution to this, the only solution that i've came up with is using an extra condition, the problem is the field changes every month (period) and not all the records are updated but I need to retrieve them all... (if an asset is depreciated there wont be anymore records relating that asset in that table)
I'm sorry if this is confusing, I'll try my best to explain
The report needs to have for each supplier registered a list of the assets that supplies, their description, their current location, it's price, and how much money still needs to be depreciated from the asset.
So, what I'm doing it's first getting the list of suppliers, then getting the list of assets associated with a location (Using cursors) then I try to calculate how much money needs to be depreciated, there's a table called 'DEPRECIACIONES' that stores the asset, the period, and how much money has been depreciated from that asset for each period and for each asset that hasn't been completely depreciated. The problem comes when I try to calculate the MAX amount of money depreciated for an asset and then selecting the row for that item that has that MAX amount, I'm sure i'm doing something wrong, my TSQL and general database knowledge is not good and I'm trying to learn by myself.
I've uploaded the schema, tables and the stored procedure that throws the wrong output here:
http://sqlfiddle.com/#!3/78c32
The Right output should be something like this:
Proveedor | Activo | Descripcion | Ubicacion Actual | Costo Adquisicion | Saldo sin depreciar | Periodo
Supplier | Asset | Description | Current Location | Cost | Money to be depreciated | Period
-------------------------------------------------------------------------------------------
Monse |ActivoT| texthere | 1114 |2034.50| RANDOM NUMBER HERE |RandomP
Monse |cesart | texthere | 4453 |4553.50| RANDOM NUMBER HERE |RandomP
nowlast | activ | texthere | 4453 |1234.65| RANDOM NUMBER HERE |RandomP
nowlast |augusto| texthere | 4450 |4553.50| RANDOM NUMBER HERE |RandomP
Sara |Activo | texthere | 1206 |746.65 | RANDOM NUMBER HERE |RandomP
I'd really appreciate telling me what i'm doing wrong (which is probably a lot) and how to fix it, thank you in advance.
Good skills in giving complete information via SqlFiddle.
I don't have a complete answer for you, but this may help.
Firstly, ditch the cursor - it's hard to debug and possibly slow. Refactor to a SELECT statement. This is my attempt, which should be logically equivalent to your code:
SELECT
p.Proveedor,
a.Activo,
a.Descripcion,
Ubi.Ubicacion,
saldo_sin_depreciar = a.Costo_adquisicion - d.Monto_acumulado,
d.Periodo
FROM
PROVEEDORES p
INNER JOIN ACTIVOS_FIJOS a ON a.Proveedor = p.Proveedor
INNER JOIN DEPRECIACIONES d ON a.Activo = d.Activo
INNER JOIN
(
SELECT
MAX(d1.Monto_acumulado) AS MaxMonto
FROM DEPRECIACIONES d1
INNER JOIN DEPRECIACIONES d2
ON d1.Monto_acumulado = d2.Monto_acumulado
) MaxAe
ON d.Monto_acumulado = MaxAe.MaxMonto
INNER JOIN ACTIVO_UBICACION Ubi ON a.activo = ubi.activo
INNER JOIN
(
SELECT
activo,
ubicacion,
Fecha_Ubicacion,
RowNum = row_number() OVER ( partition BY activo ORDER BY abs(datediff(dd, Fecha_Ubicacion, getdate())))
FROM
ACTIVO_UBICACION
) UbU
ON UbU.ubicacion = Ubi.Ubicacion
WHERE
-- a.Activo IS NOT NULL AND
UbU.RowNum = 1
ORDER BY
p.Proveedor
COMMENTS
I've moved the WHERE criteria that are defining the joins up into ON clauses in the table list, that makes it easier to see how you are joining the tables.
Note that all the joins are INNER, which may not be what you want - you may need some LEFT JOIN's, I don't understand the logic enough to say.
Also, in your cursor procedure the Ubi and UbU parts don't seem to explicitly join with the rest of the tables, so I've pencilled-in an INNER JOIN on the activo column, as this is the way the tables join in the FK relationship.
In your cursor code, you would effectively get a CROSS JOIN which is probably wrong and also expensive to run.
The WHERE clause a.Activo IS NOT NULL is not required, because the INNER JOIN ensures it.
Hope this helps you sort it out.
I ended up using another query for the cursor and fixed the problem. It's probably not optimal but it works. Whenever I learn more database related stuff I'll optimize it.
Here's the new query:
DECLARE P CURSOR STATIC
FOR SELECT a.Proveedor, actub.activo, actub.ubicacion FROM [SISACT].PROVEEDORES p,[SISACT].ACTIVOS_FIJOS a, (SELECT activo, ubicacion, Fecha_Ubicacion, row_number() OVER (
partition BY activo ORDER BY abs(datediff(dd, Fecha_Ubicacion, getdate()))
) AS RowNum FROM [SISACT].ACTIVO_UBICACION) actub WHERE RowNum = 1 AND a.Proveedor = p.Proveedor AND actub.activo = a.Activo
OPEN P
FETCH NEXT FROM P INTO #p, #a, #u
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #activo = a.Activo, #descripcion = a.Descripcion, #costo_adquisicion = a.Costo_adquisicion, #saldo_depreciado = MaxAe.MaxMonto, #periodo = d.Periodo
FROM [SISACT].ACTIVOS_FIJOS a, [SISACT].DEPRECIACIONES d, SISACT.PROVEEDORES pro, SISACT.ACTIVO_UBICACION actu, (SELECT MAX(d1.Monto_acumulado) AS MaxMonto FROM [SISACT].DEPRECIACIONES d1 INNER JOIN [SISACT].DEPRECIACIONES d2 ON d1.Monto_acumulado = d2.Monto_acumulado WHERE d1.Activo = #a AND d2.Activo = #a) MaxAe
WHERE a.Activo = d.Activo AND a.Activo = #a AND d.Activo = #a AND a.Proveedor = #p AND actu.Activo = #a AND actu.Ubicacion = #u
SET #saldo_sin_depreciar = #costo_adquisicion - #saldo_depreciado
FETCH NEXT FROM P INTO #p, #a, #u
END
CLOSE P
DEALLOCATE P