How to query Microstrategy metadata? - microstrategy

I've been working in the past few years with Cognos 10 and Cognos 11 but my company has Microstrategy (I'm a newbie in Microstrategy). So I want to create an embedded query to know which last objects were modified by an user and that sort of things. I know which tables to query because I googled it and I found this blog entry, but I don't know the schema of this tables.
Can someone help me to acomplish this?
Thanks in advance.

You can use the modification date (create_time, mod_time) in the object table.
SELECT
project_id,
object_id,
object_type,
subtype,
object_name,
abbreviation,
description,
version_id,
parent_id,
owner_id,
hidden,
**create_time,
mod_time,**
object_uname,
object_state,
locale,
extended_type,
view_media,
icon_path
FROM
meta.dssmdobjinfo;

If you are on about MetaData queries:
SELECT DISTINCT B.OBJECT_NAME AS NOMBRE,
A.USER_ID,
C.OBJECT_NAME AS CAMBIADO_POR,
D.CREATE_TIME AS F_CREACION,
D.MOD_TIME AS F_MODIFICACION
FROM DSSMDJRNINFO A
JOIN DSSMDJRNOBJD B
ON A.TRANSACTION_ID = B.TRANSACTION_ID
JOIN DSSMDOBJINFO C
ON A.USER_ID = C.OBJECT_ID
JOIN DSSMDOBJINFO D
ON B.OBJECT_NAME = D.OBJECT_NAME
AND (SYSDATE - 7) <= (D.MOD_TIME - 0);
Source: http://khaidoan.wikidot.com/mstr-metadata-queries

Related

SQL how to display group by results in columns postgresSQL

I used a** group by **id and year in a SQL query to display the following table :
QueySQL
select s.id as societe, typecombustible,extract(YEAR from p.datedebut) as yearrr
,sum(quantiteconsommee) as somme
from sch_consomind.consommationcombustible, sch_referentiel.societe s, sch_referentiel.unite u,sch_referentiel.periode p
where unite=u.id and s.id=u.societe_id and p.id=periode
group by s.id, typecombustible, yearrr
order by yearrr
But, I want to display the result by columns, like the following table
Searching in google and StackOverflow I found PIVOT function which is available in SQL Server, but I use PostgreSQL
You can use filtered aggregation:
select s.id as societe,
c.typecombustible,
sum(c.quantiteconsommee) filter (where extract(YEAR from p.datedebut) = 2020) as "2020",
sum(c.quantiteconsommee) filter (where extract(YEAR from p.datedebut) = 2021) as "2021",
sum(c.quantiteconsommee) filter (where extract(YEAR from p.datedebut) = 2022) as "2022"
from sch_consomind.consommationcombustible c
join sch_referentiel.societe s on c.unite = u.id
join sch_referentiel.unite u on s.id = u.societe_id
join sch_referentiel.periode p on p.id = c.periode
group by s.id, c.typecombustible
order by s.id, c.typecombustible;
And before you ask: no, this can not be made "dynamic". A fundamental restriction of the SQL language is, that the number, names and data types of all columns of a query must be known before the database starts retrieving the data.

HQL equivalent for postgresql query

I am trying to figure out the HQL equivalent of my query that has 2 subqueries, what I'm trying to do is I am getting the max amount for the past 6 months and then group them by month, and then I will get the average of the past 6 month result. And since the rows have version column, I also need to get maxed version for that specific row.
Here is my query, I'm using postgres by the way. Any help would be appreciated as I'm really having a hard time. Thanks in advance.
select avg(amount1) as maxField1 from
(
select max(amount1) as amount1 from table1 a
where a.id = :id
and a.date between :startDate
and :endDate
and a.version =
(
select max(b.version) from table1 b
where a.id = b.id
and a.date = b.date
)
group by to_char(a.date, 'YYYYMM')
);

Missing Weeks View

I have 2 tables which I need to compare to find missing data.
TableA: Definition table
Year, Week, cmp_code, [other columns]
TableB: Cash Receipts
Year, WeekNo, FranchiseID
TableA has all the possible combinations of ID week and year we should have data for. TableB is the data we actually have. I need to list out what we don't have yet, so the delta for B-A. How do I construct the query to find these missing values?
You can use NOT EXISTS
SELECT [Year], [Week], ID
FROM TableA AS a
WHERE NOT EXISTS
( SELECT 1
FROM TableB AS b
WHERE b.[Year] = a.[Year]
AND b.[Week] = a.[Week]
AND b.ID = a.ID
);
You can use theexceptset operator to return the difference between two sets:
SELECT [Year], [Week], cmp_code FROM TableA
EXCEPT
SELECT [Year], [WeekNo], FranchiseID FROM TableB
This will return the rows in TableA that doesn't have exact matches in TableB. The same result can be achieved using a correlatednot existsquery, or aleft join. Thenot existsshould perform best.

Two different group by clauses in one query?

First time posting here, a newbie to SQl, and I'm not exactly sure how to word this but I'll try my best.
I have a query:
select report_month, employee_id, split_bonus,sum(salary) FROM empsal
where report_month IN('2010-12-01','2010-11-01','2010-07-01','2010-04-01','2010-09-01','2010-10-01','2010-08-01')
AND employee_id IN('100','101','102','103','104','105','106','107')
group by report_month, employee_id, split_bonus;
Now, to the result of this query, I want to add a new column split_bonus_cumulative that is essentially equivalent to adding a sum(split_bonus) in the select clause but for this case, the group buy should only have report_month and employee_id.
Can anyone show me how to do this with a single query? Thanks in advance.
Try:
SELECT
report_month,
employee_id,
SUM(split_bonus),
SUM(salary)
FROM
empsal
WHERE
report_month IN('2010-12-01','2010-11-01','2010-07-01','2010-04-01','2010-09-01','2010-10-01','2010-08-01')
AND
employee_id IN('100','101','102','103','104','105','106','107')
GROUP BY
report_month,
employee_id;
Assuming you're using Postgres, you might also find window functions useful:
http://www.postgresql.org/docs/9.0/static/tutorial-window.html
Unless I'm mistaking, you want something that resembles the following:
select report_month, employee_id, salary, split_bonus,
sum(salary) over w as sum_salary,
sum(split_bonus) over w as sum_bonus
from empsal
where ...
window w as (partition by employee_id);
CTEs are also convenient:
http://www.postgresql.org/docs/9.0/static/queries-with.html
WITH
rows as (
SELECT foo.*
FROM foo
WHERE ...
),
report1 as (
SELECT aggregates
FROM rows
WHERE ...
),
report2 as (
SELECT aggregates
FROM rows
WHERE ...
)
SELECT *
FROM report1, report2, ...

Aggregate function with Date on Postgres

I'm kind of rusty on my SQL, maybe you can help me out on this query.
I have these two tables for a tickets system (I'm omitting some fields):
table tickets
id - bigint
subject - text
user_id - bigint
closed - boolean
first_message - bigint
(foreign key, for next table's id)
last_message - bigint
(same as before)
table ticket_messages
creation_date
I need to query the closed tickets, and make an average of the time spent between the first message creation_date and the last message creation_date. This is what I've done so far:
SELECT t.id, t.subject, tm.creation_date
FROM tickets AS t
INNER JOIN ticket_messages AS tm
ON tm.id = t.first_message
OR tm.id = t.last_message
WHERE t.closed = true
I'm looking for some group by or aggregate function to get all the data from the table, and try to calculate the time spent between last and first, also trying to display the dates for the first and last message.
UPDATE I added an inner Join with the second table instead of "OR", now I get both dates, and I can find the sum from my application:
SELECT t.id, t.subject, tm.creation_date, tm2.creation_date
FROM tickets AS t
INNER JOIN ticket_messages AS tm
ON tm.id = t.first_message
INNER JOIN ticket_messages as tm2
ON tm2.id = t.last_message
WHERE t.closed = true
I think that did it...
Something like this should do for getting the nr of days elapsed. You might need to put this in a subquery to easily pull out more fields from 'tickets'.
SELECT t.id,AVG(tlast.creation_date - tfirst.creation_date)
FROM tickets AS t
INNER JOIN ticket_messages AS tfirst
ON tm.id = t.first_message
INNER JOIN ticket_messages AS tlast
ON tm.id = t.last_message
WHERE t.closed = true
GROUP BY t.id
Which might lead to(not tested..) e.g.
select t.id,t.subject,sub.nr_days
FROM (
SELECT t.id,AVG(tlast.creation_date - tfirst.creation_date) as nr_days
FROM tickets AS t
INNER JOIN ticket_messages AS tfirst
ON tm.id = t.first_message
INNER JOIN ticket_messages AS tlast
ON tm.id = t.last_message
WHERE t.closed = true
GROUP BY t.id ) AS sub
INNER JOIN tickets AS t
ON sub.id = t.id;
You are trying to combine two queries into one and trying to get the data from three rows of data from two tables. Both need to be fixed.
First of all, you should not attempt to mix aggregate data (such as averages) with the details for single items - you need separate queries for that. You can do it, but the output is repetitious and therefore wasteful (all the single items in a group will have the same aggregate data).
Secondly, you need to find the first message and the last message for a given ticket. Hence, that query is:
SELECT t.id, t.subject, tm1.creation_date as start, tm2.creation_date as end,
tm2.creation_date - tm1.creation_date as close_interval
FROM tickets AS t
INNER JOIN ticket_messages AS tm1 ON t.last_message = tm1.id
INNER JOIN ticket_messages AS tm2 ON t.last_message = tm2.id
WHERE t.closed = true
This gives you three rows of data per result row - as required. The computed value should be an interval type - assuming that PostgreSQL actually has that type. (In Informix, the type would effectively be INTERVAL DAY(n) for a suitable n, such as 9.)
You can average those intervals, now. You can't average dates because dates cannot be added together and cannot be divided; averaging involves both summing and dividing. Intervals can be added and divided.