Resource modules from a course in MOODLE3.5 - moodle

What would be the best way to track resource modules from a course.
Here is my attempt, but not satisfied from specifying resource id's.
SELECT cmc.coursemoduleid
FROM mdl_course_modules_completion cmc
JOIN mdl_course_modules cm ON cm.id = cmc.coursemoduleid
JOIN mdl_modules m ON m.id= cm.module
WHERE cm.deletioninprogress=0
AND m.id IN (1,3,8,11,12,15,17,20)

Since you are using (INNER) JOIN you may strict results by course id like this:
SELECT cmc.coursemoduleid
FROM mdl_course_modules_completion cmc
JOIN mdl_course_modules cm ON cm.id = cmc.coursemoduleid AND cm.course = YOURCOURSEID
JOIN mdl_modules m ON m.id= cm.module
WHERE cm.deletioninprogress=0 AND m.name IN ('resource', 'page', 'url')
UPDATE
The info about module being a resource is not stored in database. But you may explicitly point out all module names you are interested in. The only downside is, if you decide to install new resource third party module you'll have to update your SQL

Related

Convert LEFT JOIN query to Ecto

I have some queries I need migrate to Ecto and for maintainability reasons, I'd rather not just wrap them in a fragment and call it a day.
They have a lot of LEFT JOINs in them and as I understand from this answer, a left_join in Ecto does a LEFT OUTER JOIN by default. I can't seem to figure out how to specify to Ecto that I want a LEFT INNER JOIN, which is the default behavior for a LEFT JOIN in Postgresql.
To look at a toy example, let's say posts in our database can be either anonymous or they can have a creator. I have a query to get just enough info to make a post preview, but I only want non-anonymous posts to be included:
SELECT
p.id,
p.title,
p.body,
u.name AS creator_name,
u.avatar AS creator_avatar,
FROM posts p
LEFT JOIN users u ON p.creator_id = u.id;
I would translate that into Ecto as:
nonanonymous_posts =
from p in Post,
left_join: u in User, on: p.creator_id == u.id,
select: [p.id, p.title, p.body, u.name, u.avatar]
and Ecto spits out
SELECT
t0."id",
t0."title",
t0."body",
t1."name" AS creator_name,
t1."avatar" AS creator_avatar,
FROM "posts" AS t0
LEFT OUTER JOIN "users" as t1 ON t0."creator_id" = t1."id";
which will give back anonymous posts as well.
There is no such thing as LEFT INNER JOIN. There is only INNER JOIN and LEFT [OUTER] JOIN (OUTER part is optional, as LEFT JOIN must be outer join). So what you want is just :join or :inner_join in your Ecto query.

How to prevent OpenJPA 2.2.2 add extra cross join for multiple-root query

I have two tables that don't have a defined relation, but I'm still trying to join them together in a single query, using criteria builder API.
This query work as I want it to - synchronizing the rows from both tables:
Root<E_Application> root = q.from(E_Application.class);
Root<E_Searcher> root2 = q.from(E_Searcher.class);
q.where(cb.equal(root.get(E_Application_.packageName),
root2.get(E_Searcher_.packageName)));
q.select(cb.sum(cb.literal(1)));
the query that comes out is: select sum(1) from application t0 cross join application_searcher t1 where (t0.package_name = t1.package_name);
However, if I add another join:
Root<E_Application> root = q.from(E_Application.class);
Root<E_Searcher> root2 = q.from(E_Searcher.class);
Join<E_Application, E_AppState> j1 =
root.join(E_Application_.publicAppState);
q.where(cb.equal(root.get(E_Application_.packageName),
root2.get(E_Searcher_.packageName)));
q.select(cb.sum(cb.literal(1)));
I get an extra cross join, and end up with a Cartesian product: SELECT SUM(1) FROM application t0 CROSS JOIN application t1 CROSS JOIN application_search t3 INNER JOIN application_state t2 ON t1.PUBLICAPPSTATE_ID = t2.id WHERE (t0.package_name = t3.package_name)
Is there any way to prevent this (except for defining the proper relationship between Application and Searcher)? Is this a proper implementation of the spec? It's sort of weird that the resulting query effectively has a root that I didn't explicitly request, and don't have control over...
The database is postgres, if it matters.
P.S. The reason there is no relationship is because these two tables have their PKs the same, and you can't have a PK that is also an entity reference.

SQL Server 2008: many to many tables with relational tables ordering field + grouping

To understand what I need, here is the table's I'm using diagram: http://pascalc.nougen.com/stuffs/diagram.png
I need to get a project's properties + all it's relation, all listed based on the corresponding relational tables' OrderNumber column.
Let's say I need "Project Z", I want to get:
Project's BaseUrl, ... where ID = #ID
All testsuites associated to that project, listed by ProjectsToTestSuites.OrderNumber
All testcases associated to the matching testsuites, listed by TestSuitesToTestCases.OrderNumber
All testaction associated to the matching testcases, listed by TestCasesToTestActions.OrderNumber
So far, all my attempts are returning back results with mixed ordering. A testcase is mixed inside a testsuite it doesn't belong to and alike.
I try to avoid using cursors (loop each relation in specific order required), tried the use of UNION but couldn't get it to work either.
I wouldn't have troubles with cursor but if a solution exists withuout the need to use it, I prefer of course.
Thanks
If you want a flat result you could start with something like this (untested)
select
p.Id,
p.BaseUrl,
ts.*,
tc.*,
ta.*,
pts.OrderNumber as SuitesOrder,
tstc.OrderNumber as CasesOrder,
tcta.OrderNumber as ActionsOrder
from
Projects p
join
ProjectToTestSuites pts
on pts.Projects_Id = p.Id
join
TestSuites ts
on ts.Id = pts.TestSuites_Id
join
TestSuitesToTestCases tstc
on tstc.TestSuites_Id = ts.Id
join
TestCases tc
on tc.Id = tstc.TestCases_Id
join
TestCasesToTestActions tcta
on tcta.TestCases_Id = tc.Id
join
TestActions ta
on ta.Id = tcta.TestActions_Id
where
p.Id = #Id
order by
pts.OrderNumber,
tstc.OrderNumber,
tcta.OrderNumber

t-sql condition placement

Should SQL Server yield the same results for both of the queries below? The primary difference is the condition being placed in the WHERE clause with the former, and with the latter being placed as a condition upon the join itself.
SELECT *
FROM cars c
INNER JOIN parts p
ON c.CarID = p.CarID
WHERE p.Desc LIKE '%muffler%'
SELECT *
FROM cars c
INNER JOIN parts p
ON c.CarID = p.CarID
AND p.Desc LIKE '%muffler%'
Thanks in advance for any help that I receive upon this!
For INNER JOINS it will make no difference to semantics or performance. Both will give the same plan. For OUTER JOINs it does make a difference though.
/*Will return all rows from cars*/
SELECT c.*
FROM cars c
LEFT JOIN parts p
ON c.CarID = p.CarID AND c.CarID <> c.CarID
/*Will return no rows*/
SELECT c.*
FROM cars c
LEFT JOIN parts p
ON c.CarID = p.CarID
WHERE c.CarID <> c.CarID
For inner joins the only issue is clarity. The JOIN condition should (IMO) only contain predicates concerned with how the two tables in the JOIN are related. Other unrelated filters should go in the WHERE clause.
For inner joins the two queries should yield exactly the same results. Are you seeing a difference?
Yes, they both get the same results. The difference is when the condition is checked, if during the join or afterwards.
The execution plan will be identical in your example. Next to the parse button should be the "Show execution plan" button. It will give you a clearer picture.
I think in a more complex query with many joins it can be an issue in efficiency, as stated above, before or after.
EDIT: sorry assuming your using sql server management studio.
My recommendation for this kind of situation would be:
put the JOIN condition (what establishes the "link" between the two tables) - and only that JOIN condition - after the JOIN operator
any additional conditions for one of the two joined tables belongs in the regular WHERE clause
So based on that, I would always recommend to write your query this way:
SELECT
(list of columns)
FROM
dbo.cars c
INNER JOIN
dbo.parts p ON c.CarID = p.CarID
WHERE
p.Desc LIKE 'muffler%'
It seem "cleaner" and more expressive that way - don't "hide" additional conditions behind a JOIN clause if they don't really belong there (e.g. help establish the link between the two tables being joined).

JOIN that doesn't exclude all records if one side is null

I have a fairly conventional set of order entry tables divided by:
Orders
OrdersRows
OrdersRowsOptions
The record in OrderRowOptions is not created unless needed. When I create a set of joins like
select * from orders o
inner join OrdersRows r on r.idOrder = o.idOrder
inner join ordersrowsoptions ro on ro.idOrderRow = r.idOrderRow
where r.idProduct = [foo]
My full resultset is blank if no ordersrowsoptions records exist for the given product.
what's the correct syntax to return records even if no records exist at one of the join clauses?
thx
select * from orders o
inner join OrdersRows r on r.idOrder = o.idOrder
left join ordersrowsoptions ro on ro.idOrderRow = r.idOrderRow
where r.idProduct = [foo]
Of course you should not use select * in any query but especially never when doing a join. The repeated fields are just wasting server and network resources.
Since you seem unfamiliar with left joins, you probably also need to understand the concepts in this:
http://wiki.lessthandot.com/index.php/WHERE_conditions_on_a_LEFT_JOIN
LEFT JOIN / RIGHT JOIN.
Edit: yes, the following answer, given earlier, is correct:
select * from orders o
inner join OrdersRows r on r.idOrder = o.idOrder
left join ordersrowsoptions ro on ro.idOrderRow = r.idOrderRow
where r.idProduct = [foo]
LEFT JOIN (or RIGHT JOIN) are probably what you are looking for, depending on which side of the join no rows may appear.
Interesting, do you want to get all orders that have that product in them? The other post is correct that you have to use LEFT or RIGHT OUTER JOINS. But if you want to get entire orders that have that product then you'd need a more complex where clause.